tag:blogger.com,1999:blog-29090883498758428282024-03-12T21:53:15.701-04:00Extending FrameMakerLearn how to customize Adobe FrameMaker with ExtendScript scripting.Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.comBlogger83125tag:blogger.com,1999:blog-2909088349875842828.post-85675805802466697902012-04-05T16:55:00.000-04:002012-04-05T16:55:42.293-04:00Working with Structured Documents<div dir="ltr" style="text-align: left;" trbidi="on">When working with a structured document, you can choose to navigate the document using the tree of elements. Or, if it is more convenient, you can work with the document<i> as if</i> it does not have structure. That is, you can work with paragraphs in the main flow exactly as you would in unstructured FrameMaker.<br />
<br />
Is there a downside to this approach? The answer is, it depends. If you are cutting and pasting or otherwise adding content, working outside the element structure may lead you to make changes that leave the structure invalid. But if you are simply inspecting the document or you are working with content that is not part of the element structure (e.g.. marker content), feel free to do whatever is easiest.<br />
<br />
<br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com3tag:blogger.com,1999:blog-2909088349875842828.post-23347912566085430402012-04-05T11:38:00.002-04:002012-04-05T11:38:36.399-04:00Selecting an Entire Element<div dir="ltr" style="text-align: left;" trbidi="on">
Selecting elements is tricky business. You will find helpful information in the <i>FDK Programmer's Guide. </i>I happen to have the one for version 6 on hand. In that version, you should refer to pages 366-7.<br />
<br />
The key idea is to create an <span style="font-family: "Courier New",Courier,monospace;">ElementRange </span>that refers to the appropriate selection and then set the document's element selection to be that range. The following function sets the specified document's element selection to be the element passed in.<br />
<br />
Element ranges have a beginning and an end. They consist of parent, child, and offset information. <br />
<br />
The parent element is the containing element for both the beginning and end of the range. The starting child is the element itself. The ending child is the element's next sibling element. As the whole element is being selected, both offsets are zero. <br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">//Selects the specified element in the specified document</span><br />
<span style="font-family: "Courier New",Courier,monospace;">function setElementSelection(doc, element) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> var eRange = new ElementRange;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> eRange.beg.parent = element.ParentElement;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> eRange.beg.child = element;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> eRange.beg.offset = 0;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> eRange.end.parent = element.ParentElement;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> eRange.end.child = element.NextSiblingElement;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> eRange.end.offset = 0;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> doc.ElementSelection = eRange; </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">}</span><br /></div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-76603029302157431852012-03-14T20:23:00.000-04:002012-03-14T20:23:45.439-04:00Opening Files Off Screen<div dir="ltr" style="text-align: left;" trbidi="on">If you are processing a large number of files without user interaction, consider opening those files off screen. This allow your script to work faster (as there is no need to update the display) and to do its work without screen fireworks.<br />
<br />
Use <span style="font-family: "Courier New",Courier,monospace;">Open() </span>and set the open parameter <span style="font-family: "Courier New",Courier,monospace;">Constants.FS_MakeVisible</span> to <span style="font-family: "Courier New",Courier,monospace;">False</span> to open a file off screen. Files opened this way can be modified in exactly the same way as files that are on screen.<br />
<br />
If you work with files in this way, keep in mind is that your script must take total responsibility for managing off screen files. When a script is done with an off screen file, it must save (if changes are to be retained) and close the file. Failing to do so leaves the file locked and open but inaccessible to an end user.<br />
<br />
There may be a case where you want to open a file off screen, work with that file, and then make it visible to users. To do so, set the document property, FS_<span style="font-family: "Courier New",Courier,monospace;">MakeVisible </span>to <span style="font-family: "Courier New",Courier,monospace;">True </span>when you are ready to reveal the file to users. <br />
<br />
<br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-29558877782624590102012-03-13T13:13:00.000-04:002012-03-13T13:13:43.338-04:00Opening Book Files when there are Issues<div dir="ltr" style="text-align: left;" trbidi="on">If you use <span style="font-family: "Courier New",Courier,monospace;">SimpleOpen() </span>to open book files non-interactively, files with missing graphics, missing fonts, or other issues will not open. Use <span style="font-family: "Courier New",Courier,monospace;">Open()</span> with an appropriate set of parameters to solve this problem. <br />
<br />
The following function sets up open preferences that allow files of the following types to open without user interaction:<br />
<ul style="text-align: left;"><li>Files which reference missing files.</li>
<li>Files that are in an old FM version.</li>
<li>Files with missing font issues.</li>
<li>Files that are locked.</li>
</ul><div style="font-family: "Courier New",Courier,monospace;">function getOpenPrefs() {<br />
var params, i;<br />
<br />
params = GetOpenDefaultParams();<br />
<br />
i = GetPropIndex(params, Constants.FS_RefFileNotFound);<br />
params[i].propVal.ival =<br />
Constants.FV_AllowAllRefFilesUnFindable; <br />
i = GetPropIndex(params, Constants.FS_FileIsOldVersion);<br />
params[i].propVal.ival = Constants.FV_DoOK;<br />
i = GetPropIndex(params, Constants.FS_FontChangedMetric);<br />
params[i].propVal.ival = Constants.FV_DoOK; <br />
i = GetPropIndex(params, Constants.FS_FontNotFoundInCatalog);<br />
params[i].propVal.ival = Constants.FV_DoOK; <br />
i = GetPropIndex(params, Constants.FS_FontNotFoundInDoc);<br />
params[i].propVal.ival = Constants.FV_DoOK; <br />
i = GetPropIndex(params, Constants.FS_LockCantBeReset);<br />
params[i].propVal.ival = Constants.FV_DoOK; <br />
i = GetPropIndex(params, Constants.FS_FileIsInUse);<br />
params[i].propVal.ival = Constants.FV_OpenViewOnly; <br />
return (params);<br />
}</div><div style="font-family: "Courier New",Courier,monospace;"> </div><div style="font-family: Arial,Helvetica,sans-serif;">The function to open the book using these parameters is shown here:</div><div style="font-family: "Courier New",Courier,monospace;"><br />
</div><span style="font-family: "Courier New",Courier,monospace;">function openBookFiles(book) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> var doc, component, compName;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> var openParams, openReturnParams;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> openParams = getOpenPrefs ();</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> openReturnParams = new PropVals();</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> component =book.FirstComponentInBook;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> while(component.ObjectValid() ){ </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> compName = component.Name;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> doc = Open(compName, openParams, openReturnParams);</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> component = component.NextComponentInBook;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> } </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">} </span></div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-48675013624231258702012-03-12T15:30:00.000-04:002012-03-12T15:30:11.844-04:00Saving FM Binary in Old Version<div dir="ltr" style="text-align: left;" trbidi="on">If you have ever needed to revert FrameMaker files to an older version, the following script does so automatically. It works on the active document but you could convert it to work on a book or a directory of files.<br />
<br />
The key to the script is the<span style="font-family: "Courier New",Courier,monospace;"> Save()</span> method which allows you to set the file type as desired. I have chosen FrameMaker 9 (<span style="font-family: "Courier New",Courier,monospace;">FV_SaveFmtBinary90</span>) but you can go as far back as FrameMaker 6 (<span style="font-family: "Courier New",Courier,monospace;">FV_SaveFmtBinary60</span>).<br />
<br />
I chose not to change the file name. I end the script by closing the FM 10 version of the file without saving it. The FM9 version is already on disk.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">var doc, name, saveParams, i;</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">doc = app.ActiveDoc;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">name = doc.Name;</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">saveParams = GetSaveDefaultParams();</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">returnParams = new PropVals();</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">i = GetPropIndex(saveParams, Constants.FS_FileType);</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">saveParams[i].propVal.ival =Constants.FV_SaveFmtBinary90;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">doc.Save(name, saveParams, returnParams);</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">doc.Close(Constants.FF_CLOSE_MODIFIED);</span><br />
<br />
After running the script, I opened the test file just to convince myself this really works. <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-0n55o3CXcdY/T15OnfokZGI/AAAAAAAAAVg/OlUDvxuszO0/s1600/oldvers.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="189" src="http://2.bp.blogspot.com/-0n55o3CXcdY/T15OnfokZGI/AAAAAAAAAVg/OlUDvxuszO0/s320/oldvers.png" width="320" /></a></div><br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com4tag:blogger.com,1999:blog-2909088349875842828.post-63790999353423449122012-03-11T15:17:00.000-04:002012-03-11T15:17:12.904-04:00Using SimpleOpen() without User Interaction<div dir="ltr" style="text-align: left;" trbidi="on"><span style="font-family: "Courier New",Courier,monospace;">SimpleOpen()</span> can be called interactively or without user interaction. This distinction makes a difference if you are dealing with files that have issues.<br />
<br />
If you are calling <span style="font-family: "Courier New",Courier,monospace;">SimpleOpen()</span> interactively, the user decides what to do when there are missing fonts, locked files, or other problematic situations.<br />
<br />
If you call <span style="font-family: "Courier New",Courier,monospace;">SimpleOpen()</span> without user interaction FrameMaker defaults to very conservative behavior.<br />
I created a simple a test to demonstrate this behavior. I cobbled together a set of files, each with a distinct issue, and put those files into a FrameMaker book. Each of my four files has one of the following issues:<br />
<ul style="text-align: left;"><li>It is locked.</li>
<li>It contains missing graphics.</li>
<li>It uses unavailable fonts.</li>
<li>It is in an older FrameMaker version. </li>
</ul>Opening these files from the user interface brings up a dialog that allow the user to proceed or abort the open. Opening these files using the following code produces no user interaction and only one of the files opens: the locked file is opened in view only mode. <br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">doc = SimpleOpen(compName, false); </span></div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com2tag:blogger.com,1999:blog-2909088349875842828.post-41902029618798293612012-02-22T14:40:00.000-05:002012-02-22T14:40:43.139-05:00Opening a File with User Interaction<div dir="ltr" style="text-align: left;" trbidi="on">The easiest way to open a file is with <span style="font-family: "Courier New",Courier,monospace;">SimpleOpen()</span>. This is the analog to <span style="font-family: "Courier New",Courier,monospace;">SimpleSave()</span> discussed <a href="http://extendingframemaker.blogspot.com/2012/01/saving-document-without-user.html">here.</a><br />
<br />
If you do the open interactively, you do not need to know the file's location. You simply let the user locate the proper file.<br />
<br />
The following script passes an empty string for the <span style="font-family: "Courier New",Courier,monospace;">fileName </span>parameter. FrameMaker assumes the file is the last one opened. <br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">var doc;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">doc = SimpleOpen("", true);</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-7XQRK1_503Y/T0VEFeEOBFI/AAAAAAAAAVY/_wLeBsdleug/s1600/simpleopen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="235" src="http://3.bp.blogspot.com/-7XQRK1_503Y/T0VEFeEOBFI/AAAAAAAAAVY/_wLeBsdleug/s320/simpleopen.png" width="320" /></a></div><br />
To open a file without user interaction, you need to pass it is full pathname and <span style="font-family: "Courier New",Courier,monospace;">false </span>for the second parameter. </div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com2tag:blogger.com,1999:blog-2909088349875842828.post-15158877961863476892012-02-20T13:21:00.000-05:002012-02-20T13:21:33.301-05:00Working with Book Components<div dir="ltr" style="text-align: left;" trbidi="on">You might be tempted to think of FrameMaker books as containing documents. In fact, they contain book components which reference the files that when opened become FrameMaker documents.<br />
<br />
To work with all of the documents in a book, you must traverse the list of book components and open each component in turn.<br />
<br />
The list of book components is an ordered list. You can start with the <span style="font-family: "Courier New",Courier,monospace;">FirstComponentInBook</span>. Having found that component, you can use its <span style="font-family: "Courier New",Courier,monospace;">NextComponentInBook </span>property to find the next book component.<br />
<br />
It is also possible to traverse a books components from last to first. In this case you start with <span style="font-family: "Courier New",Courier,monospace;">LastComponentInBook </span>and use the component's <span style="font-family: "Courier New",Courier,monospace;">PrevComponentInBook </span>property to move up the list.<br />
<br />
The following code snippet shows how you to traverse a book's components from first to last. <br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">component =book.FirstComponentInBook;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">while(component.ObjectValid() ){</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> doSomething();</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> component = component.NextComponentInBook;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">}</span></div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-46149553927677567282012-02-20T13:20:00.000-05:002012-02-20T13:20:41.201-05:00Working with the Active book<div dir="ltr" style="text-align: left;" trbidi="on">The <span style="font-family: "Courier New",Courier,monospace;">ActiveBook </span>is an exact analog of the <span style="font-family: "Courier New",Courier,monospace;">ActiveDoc</span>. It refers to the book that has the user focus.<br />
<br />
There can be an active book <i>or </i>an active document but not both at the same time. It is also possible that there is neither an active book <i>nor </i>an active document. <br />
<br />
When working with either an active book or an active document, you should check for the possibility that what you are seeking does not exist.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">var doc, book;<br />
<br />
book = app.ActiveBook;<br />
if (book.ObjectValid()) {<br />
Alert("Active book found", Constants.FF_ALERT_CONTINUE_NOTE);<br />
} else {<br />
doc = app.ActiveDoc;<br />
if (doc.ObjectValid()) {<br />
Alert("Active document found", Constants.FF_ALERT_CONTINUE_NOTE);<br />
} else {<br />
Alert("No active document or book found", Constants.FF_ALERT_CONTINUE_NOTE);<br />
} <br />
}</div><div style="font-family: "Courier New",Courier,monospace;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-8NtwegcaWlY/T0KISS1mRQI/AAAAAAAAAVQ/YWcR6y1l34E/s1600/noactive.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="174" src="http://1.bp.blogspot.com/-8NtwegcaWlY/T0KISS1mRQI/AAAAAAAAAVQ/YWcR6y1l34E/s320/noactive.png" width="320" /></a></div><br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-62788242106948735572012-02-04T20:34:00.000-05:002012-02-04T20:34:35.753-05:00Converting Font Style Names to Font Angle Index Values<div dir="ltr" style="text-align: left;" trbidi="on">If your script queries a text property such as font angle, the value you get back is a number and not a name. For example, the following code snippet asks what is the font angle at the text location (<span style="font-family: "Courier New",Courier,monospace;">tLoc</span>) specified. That information is returned as an integer. <br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">textProp = doc.GetTextPropVal(tLoc, Constants.FP_FontAngle);</div><div style="font-family: "Courier New",Courier,monospace;">angleIndex = textProp.propVal.ival; //integer value</div><br />
The integer value <span style="font-family: "Courier New",Courier,monospace;">angleIndex </span>is an index into an array containing the possible font angle values available in the current FrameMaker session. Use the app (session) property <span style="font-family: "Courier New",Courier,monospace;">FontAngleNames </span>to get this array of strings. <br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">angleNames = app.FontAngleNames; </div><br />
Here is that data structure as viewed in the ExtendScript DataBrowser:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-qWuAbWzbGZw/Ty3W3zh21nI/AAAAAAAAAUw/mpr8XjqIg80/s1600/angles.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="118" src="http://1.bp.blogspot.com/-qWuAbWzbGZw/Ty3W3zh21nI/AAAAAAAAAUw/mpr8XjqIg80/s400/angles.png" width="400" /></a></div><br />
The following script converts an angle name to its corresponding index in the <span style="font-family: "Courier New",Courier,monospace;">angleNames </span>array.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">function findAngleIndex(angleName) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> var angleNames, index;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> angleNames = app.FontAngleNames;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> for (index = 1; index < angleNames.len; index += 1) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> if (angleNames[index] === angleName) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> break;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> }</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> }</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> if (index === angleNames.len) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> index = null;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> }</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> return (index);</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">}</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">var index;</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">index = findAngleIndex("Italic");</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">Alert(index, Constants.FF_ALERT_CONTINUE_NOTE);</span><br />
<br />
<br />
The output is as shown here:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-bbUCo6MZCH0/Ty3cl1_LpfI/AAAAAAAAAU4/uRwFUc6fx5o/s1600/five.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-bbUCo6MZCH0/Ty3cl1_LpfI/AAAAAAAAAU4/uRwFUc6fx5o/s1600/five.png" /></a></div><br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-83598170377168710962012-01-30T19:13:00.000-05:002012-01-30T19:13:10.778-05:00Text Item and Line Ends<div dir="ltr" style="text-align: left;" trbidi="on">Understanding exactly what text items are produced when you call <span style="font-family: "Courier New",Courier,monospace;">GetText()</span> is critical to writing correct scripts. I have been looking at when you get a FTI_<span style="font-family: "Courier New",Courier,monospace;">CharPropsChange </span>notification upon calling <span style="font-family: "Courier New",Courier,monospace;">GetText()</span>. In particular, I am interested in what happens at line ends. <br />
<br />
Each of the examples below show what happens when you run a simple script that prints a set of requested text items including changes in character properties and line ends to the <b>Console</b>. Each file tested has one "word" consisting of the digits from 0 through 9. In each case three of the digits have been italicized using the <b>Format>Style</b> menu. <br />
<br />
I was expecting to see, among other things, an indicator of where any changes in the italic properties of the text begin and end. The problem I have found occurs when the italic text is at the end of a line. In such cases, I do not get the second FTI_<span style="font-family: "Courier New",Courier,monospace;">CharPropsChange</span> indicator I am expecting. This behavior deviates from what I knew to be the case in the FDK in earlier versions of FrameMaker. I have not yet tried this in the FM 10 FDK.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">var doc, mainflow, tItems; <br />
<br />
doc = app.ActiveDoc;<br />
mainflow = doc.MainFlowInDoc;<br />
tItems = mainflow.GetText(Constants.FTI_CharPropsChange | Constants.FTI_TextObjId | Constants.FTI_LineEnd);<br />
PrintTextItems(tItems); </div><br />
<br />
Here is a case that goes as expected, yielding a change indicator before and after the italicized text.<span style="font-family: "Courier New",Courier,monospace;"><br />
</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-ZN4dTPzmoKM/TyctgPh81yI/AAAAAAAAAUg/MjskUI18Q5w/s1600/good.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="217" src="http://3.bp.blogspot.com/-ZN4dTPzmoKM/TyctgPh81yI/AAAAAAAAAUg/MjskUI18Q5w/s320/good.png" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-dtfwL8QDtzU/TyctSUSLIwI/AAAAAAAAAUY/epWNhH23at0/s1600/good.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-dtfwL8QDtzU/TyctSUSLIwI/AAAAAAAAAUY/epWNhH23at0/s1600/good.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-s6pvcFeAJ5M/TycszfOgxFI/AAAAAAAAAUI/e7lnqp-10nI/s1600/good.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-b_xOOko_P-M/TyctqGyydwI/AAAAAAAAAUo/5AzlyGetZNI/s1600/goodout.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="131" src="http://2.bp.blogspot.com/-b_xOOko_P-M/TyctqGyydwI/AAAAAAAAAUo/5AzlyGetZNI/s320/goodout.png" width="320" /></a></div><br />
Now look at what happens when the italic text is at the end of the line. Here I get only the initial indicator. In my view, this is acceptable as this this a special end of flow case. There is no non-italic character after the italic "9".<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-Kb-f6larbR4/TycnboCc1tI/AAAAAAAAATI/TLMZ44-meMg/s1600/simpledoc.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="185" src="http://2.bp.blogspot.com/-Kb-f6larbR4/TycnboCc1tI/AAAAAAAAATI/TLMZ44-meMg/s320/simpledoc.png" width="320" /></a></div><br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-a_ZcFam5Yc4/TycoVEbTHLI/AAAAAAAAATQ/CoMuPjh3kv8/s1600/simpleout.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="128" src="http://2.bp.blogspot.com/-a_ZcFam5Yc4/TycoVEbTHLI/AAAAAAAAATQ/CoMuPjh3kv8/s320/simpleout.png" width="320" /></a></div><br />
If a carriage return is added after the italic "9", I expect but do not get the second character properties change indicator. Note that end of paragraph symbols are selectable and this one is <i>not </i>italic. <br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-P2O0WRzxlFc/Tyco0AdIkRI/AAAAAAAAATY/gtdHcjDhUC0/s1600/simpledoc2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="183" src="http://4.bp.blogspot.com/-P2O0WRzxlFc/Tyco0AdIkRI/AAAAAAAAATY/gtdHcjDhUC0/s320/simpledoc2.png" width="320" /></a></div><br />
<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-gF0lpLD12xM/TycpONyRefI/AAAAAAAAATg/R6E-eWN3CJM/s1600/simpleout2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="http://3.bp.blogspot.com/-gF0lpLD12xM/TycpONyRefI/AAAAAAAAATg/R6E-eWN3CJM/s320/simpleout2.png" width="320" /></a></div>Finally, lets use a soft return as our final character. Once again, there is only the beginning indicator. <br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-INcF7u1asl4/TycrT24fEhI/AAAAAAAAAT4/QPX1icMSS4Q/s1600/simpledoc3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="http://3.bp.blogspot.com/-INcF7u1asl4/TycrT24fEhI/AAAAAAAAAT4/QPX1icMSS4Q/s320/simpledoc3.png" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-9wsLTbxwS9g/Tycq85y2cYI/AAAAAAAAATo/KuAdgwQaPzE/s1600/simpledoc3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-_DiVUYESWDQ/TycrwLmTHOI/AAAAAAAAAUA/UAFNcXjQlIo/s1600/simpleti3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="186" src="http://2.bp.blogspot.com/-_DiVUYESWDQ/TycrwLmTHOI/AAAAAAAAAUA/UAFNcXjQlIo/s320/simpleti3.png" width="320" /></a></div><br />
<br />
I bring all this up not to be picky but because this change/bug complicates working with <i>GetText()</i>. If have I have missed something, please let me know.</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-90410027363042520182012-01-29T20:37:00.000-05:002012-01-29T20:37:31.695-05:00Customizing a Save Operation<div dir="ltr" style="text-align: left;" trbidi="on">The following script uses the <span style="font-family: "Courier New",Courier,monospace;">Save()</span> method to alter the format in which a file is saved. Using this method requires more code than <span style="font-family: "Courier New",Courier,monospace;">SimpleSave()</span> but offers a whole range of customization options. It takes three pages in the <i>Scripting Guide</i> to document the possibilities. Whatever changes you want to make, however, can be accomplished by following the model shown here:<br />
<ul style="text-align: left;"><li>Use <span style="font-family: "Courier New",Courier,monospace;">GetSaveDefaultParams()</span> to get a list of parameters whose default settings can be altered.</li>
<li>Use <span style="font-family: "Courier New",Courier,monospace;">new PropVals()</span> to create an empty parameter list to be used to return information about the <span style="font-family: "Courier New",Courier,monospace;">Save()</span> operation.</li>
<li>Use <span style="font-family: "Courier New",Courier,monospace;">GetPropIndex()</span> to locate one or more of these properties of interest.</li>
<li>Reset that properties value in the parameter list.</li>
<li>Call <span style="font-family: "Courier New",Courier,monospace;">Save()</span> passing in the save as name, and the two parameter lists. </li>
</ul>The critical function is shown here:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">function saveAsPdf(doc) {<br />
var saveParams, name, i, baseName, status, fullName;<br />
name = doc.Name; <br />
baseName = dropSuffix(name);//drops everything from last period<br />
fullName = baseName + ".pdf";<br />
saveParams = GetSaveDefaultParams();<br />
returnParams = new PropVals(); <br />
i = GetPropIndex(saveParams, Constants.FS_FileType);<br />
saveParams[i].propVal.ival =Constants.FV_SaveFmtPdf;<br />
doc.Save(fullName, saveParams, returnParams);<br />
i = GetPropIndex(returnParams, Constants.FS_SaveNativeError);<br />
status = returnParams[i].propVal.ival;<br />
if (status === Constants.FE_Success) {<br />
return (true);<br />
} else {<br />
return (false);<br />
}<br />
}</div></div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-51633449298569117772012-01-27T11:47:00.001-05:002012-01-27T17:15:27.699-05:00Creating a Marker (Correction to previous post)<div dir="ltr" style="text-align: left;" trbidi="on">When you create a marker you need to specify the marker type identifier. If you are using an built-in type, use the name found in the English user interface. <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-i8phYVSRTXI/TyLSCpH_mgI/AAAAAAAAASU/I6l4cnFX1eU/s1600/markermenu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://2.bp.blogspot.com/-i8phYVSRTXI/TyLSCpH_mgI/AAAAAAAAASU/I6l4cnFX1eU/s320/markermenu.png" width="180" /></a></div><br />
Use <span style="font-family: "Courier New",Courier,monospace;">GetNamedObject()</span> to get this identifier. Use the appropriate marker type name. (This is a document and not a session property because of the fact that new types can be added to a given document.) <br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">function createMarker(doc, pgf, offset, type, text) {<br />
var tLoc, marker, markerType;<br />
tLoc = new TextLoc(pgf, offset);<br />
marker = doc.NewAnchoredObject(Constants.FO_Marker, tLoc);<br />
markerType = doc.GetNamedObject(Constants.FO_MarkerType, type);</div><div style="font-family: "Courier New",Courier,monospace;"> marker.MarkerTypeId = markerType;<br />
marker.MarkerText = text;<br />
return 1;<br />
}</div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-tw_Av_4Uajo/TyLTtopfjOI/AAAAAAAAASc/uT2MocvKaaY/s1600/glossary.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="132" src="http://2.bp.blogspot.com/-tw_Av_4Uajo/TyLTtopfjOI/AAAAAAAAASc/uT2MocvKaaY/s400/glossary.png" width="400" /></a></div><br />
You only need to set the marker type properties for a built-in type if you want to change them. For example, add the following line of code to change the type name as displayed in the user interface.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">markerType.Name = "My glossary";</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-ZOG3V-BlFZI/TyLUkGiCdDI/AAAAAAAAASk/-jGcguFp_ZI/s1600/mygloss.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="130" src="http://3.bp.blogspot.com/-ZOG3V-BlFZI/TyLUkGiCdDI/AAAAAAAAASk/-jGcguFp_ZI/s400/mygloss.png" width="400" /></a></div><br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com1tag:blogger.com,1999:blog-2909088349875842828.post-90012524860762484082012-01-26T14:17:00.001-05:002012-01-26T15:37:37.774-05:00Saving a document without user interactionThe following script makes a trivial change to that presented in my previous post to save the active document with no user interaction.<br />
<div dir="ltr" style="text-align: left;" trbidi="on"><div style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"></span> <br />
<br />
var doc, name;</div><br />
<span style="font-family: "Courier New",Courier,monospace;">doc = app.ActiveDoc;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">name = doc.Name;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">doc.SimpleSave(name, false); //no user involvement</span></div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-36829150238846928852012-01-22T12:19:00.000-05:002012-01-22T12:19:56.856-05:00Saving a document with user interaction<div dir="ltr" style="text-align: left;" trbidi="on">If your script makes changes to a document, you will want to save that file. This post, as will the next several posts, discuss the various ways you can do so.<br />
<br />
From a scripting point of view, there are two possible ways to save a file. The first is deemed "simple" and the second is more complex to call and customizable. (In the FDK world, this option was deemed 'script-able.') The different between the two lies in the degree of configuration offered.<br />
<br />
Simple operations use default settings but do offer one big choice. They allow you to choose whether you want to do the save operation with or without user interaction.<br />
<br />
If you are doing a batch operation, you are not going to want user interaction. If, however, you are creating a command a user might call that needs user input, allowing a user to make choices regarding a save in the exact same way as he or she might had they invoked the command form the menu can be useful. <br />
<br />
The following script invokes the save dialog using a script.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">var doc, name;</div><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">doc = app.ActiveDoc;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">name = doc.Name;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">doc.SimpleSave(name, true); //true signifies user directed</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><br />
</span><br />
Here is what happens when I saved a file using this script. It is the equivalent o the user choosing <b>File>Save</b>.<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-rtTcQPvue0A/TxxD261vUfI/AAAAAAAAASE/G4-zzEuhVdc/s1600/savetest.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="251" src="http://4.bp.blogspot.com/-rtTcQPvue0A/TxxD261vUfI/AAAAAAAAASE/G4-zzEuhVdc/s400/savetest.png" width="400" /></a><a href="http://4.bp.blogspot.com/-rtTcQPvue0A/TxxD261vUfI/AAAAAAAAASE/G4-zzEuhVdc/s1600/savetest.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div><br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-54392685249743614352012-01-11T14:48:00.000-05:002012-01-11T14:48:49.077-05:00Rearranging the Tree of Elements<div dir="ltr" style="text-align: left;" trbidi="on">You can use the <span style="font-family: "Courier New",Courier,monospace;">Cut</span>, <span style="font-family: "Courier New",Courier,monospace;">Copy</span>, <span style="font-family: "Courier New",Courier,monospace;">Paste </span>methods to move selected elements around in the tree. There are, however, some special cases where you can take advantage of built-in tree manipulation functions.<br />
<ul style="text-align: left;"><li>Use the document method <span style="font-family: "Courier New",Courier,monospace;">PromoteElement()</span> to make the selected element the sibling of its former parent. <br />
<a href="http://1.bp.blogspot.com/-7uEYvmuzBQY/Tw3WaY5IsmI/AAAAAAAAARY/pNtHFz1Wils/s1600/promote.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="87" src="http://1.bp.blogspot.com/-7uEYvmuzBQY/Tw3WaY5IsmI/AAAAAAAAARY/pNtHFz1Wils/s320/promote.png" width="320" /></a></li>
<li>Use<b> </b>the document method <span style="font-family: "Courier New",Courier,monospace;">DemoteElement()</span> to make the selected element the child of its preceding sibling. <br />
<a href="http://4.bp.blogspot.com/-1724LXmT4_4/Tw3WwtZY-kI/AAAAAAAAARg/K8NIxY8FD-8/s1600/demote.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="87" src="http://4.bp.blogspot.com/-1724LXmT4_4/Tw3WwtZY-kI/AAAAAAAAARg/K8NIxY8FD-8/s320/demote.png" width="320" /></a></li>
</ul><br />
The following simple script promotes the selected element. You could easily modify it to demote an element.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">var doc;</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">doc = app.ActiveDoc;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">doc.PromoteElement();</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">if (FA_errno !== 0) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Alert(FA_errno + '');</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">} </span><br />
<br />
The script checks for an error code:<br />
<ul style="text-align: left;"><li><span style="font-family: "Courier New",Courier,monospace;">Constants.FE_WrongProduct (-60)</span> signifies that the product interface is not set to Structured FrameMaker .</li>
<li><span style="font-family: "Courier New",Courier,monospace;">Constants.FE_BadDocId (-2)</span> indicates a problem with the document identifier.</li>
<li><span style="font-family: "Courier New",Courier,monospace;">Constants.FE_BadSelectionForOperation (-59)</span> indicates that the action requested could not be taken on the selected element. For example, you cannot promote the root element or its children. </li>
</ul><br />
Here is the before and after that results from promoting the <span style="font-family: "Courier New",Courier,monospace;">p </span>element.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-ZMy06PFqvq8/Tw3cvwrgIeI/AAAAAAAAARo/FIiVUVLsra0/s1600/pselected.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="149" src="http://3.bp.blogspot.com/-ZMy06PFqvq8/Tw3cvwrgIeI/AAAAAAAAARo/FIiVUVLsra0/s320/pselected.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Before element promotion</td></tr>
</tbody></table><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-DsGUeKrN_Ks/Tw3dDPZ2VZI/AAAAAAAAARw/v8qt3lO6kzk/s1600/afterpromote.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="149" src="http://2.bp.blogspot.com/-DsGUeKrN_Ks/Tw3dDPZ2VZI/AAAAAAAAARw/v8qt3lO6kzk/s320/afterpromote.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">After element promotion</td></tr>
</tbody></table>This promote operation happens to make the structure tree invalid but the operation itself is sound.<br />
<br />
Attempting to promote the root element produces the following error code message <span style="font-family: "Courier New",Courier,monospace;">Constants.FE_BadSelectionForOperation (-59)</span> as displayed by the script. <br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-R4n9ZS6TMr0/Tw3d-R2bhNI/AAAAAAAAAR4/zxLGn4KGS58/s1600/neg59%2527.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="154" src="http://4.bp.blogspot.com/-R4n9ZS6TMr0/Tw3d-R2bhNI/AAAAAAAAAR4/zxLGn4KGS58/s200/neg59%2527.png" width="200" /></a></div></div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-493159492260183892012-01-08T15:37:00.000-05:002012-01-08T15:37:40.109-05:00Text Nodes<div dir="ltr" style="text-align: left;" trbidi="on">Text nodes appear in the element tree when a container element has multiple children some of which are containers for text and some of which are just a text string.<br />
<br />
Consider the case of an element, <span style="font-family: "Courier New",Courier,monospace;">p</span>, that allows text (<span style="font-family: "Courier New",Courier,monospace;"><TEXT></span>) and other elements as described in the EDD:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-2VZ5B3tatxQ/Twn7ml4fsfI/AAAAAAAAARA/3V7Cfeo6gPc/s1600/paraelt.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="108" src="http://4.bp.blogspot.com/-2VZ5B3tatxQ/Twn7ml4fsfI/AAAAAAAAARA/3V7Cfeo6gPc/s400/paraelt.png" width="400" /></a></div><br />
<br />
I have made a small modification to <span style="font-family: "Courier New",Courier,monospace;">oil.xml</span> to illustrate this point. The word "every" is italicized by wrapping it in the element <span style="font-family: "Courier New",Courier,monospace;">i</span>. Before this change, the <span style="font-family: "Courier New",Courier,monospace;">p </span>element had no children. Now it has three. The first and the last of these are text nodes as illustrated below. <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-qLgdtsJZNlU/Twn6CZyV4dI/AAAAAAAAAQ4/zRlG6m9qz6c/s1600/textnode.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="198" src="http://4.bp.blogspot.com/-qLgdtsJZNlU/Twn6CZyV4dI/AAAAAAAAAQ4/zRlG6m9qz6c/s400/textnode.png" width="400" /></a></div><br />
<br />
The function <span style="font-family: "Courier New",Courier,monospace;">getElementName()</span> uses the element property <span style="font-family: "Courier New",Courier,monospace;">ElementDef </span>to find the definition object and then the name property to get the name string.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">function getElementName(elem) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> var elemDef, name = null;</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> elemDef = elem.ElementDef;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> if (elemDef.ObjectValid()) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> name = elemDef.Name;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> }</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> return name;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">}</span><br />
<br />
If an element definition is <span style="font-family: "Courier New",Courier,monospace;">NULL</span>, that element is a text node. Armed with this knowledge, the <span style="font-family: "Courier New",Courier,monospace;">displayAttrs()</span> function used in a previous post can be improved.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">//writes element name and list of attributes to the console</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">function displayAttrs(elem) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> var i, name, aName, attrs;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> name = getElementName(elem);</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> if (name != null) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Console(name);</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> attrs = elem.GetAttributes();</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> for (i = 0; i < attrs.len; i++) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> aName = attrs[i].name;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Console( " " + aName); </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> }</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> } else {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Console("Selected element is a text node");</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> }</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">} </span><br />
<br />
Here a text node is selected:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-2h0rj_IPJvI/Twn9dGkXptI/AAAAAAAAARI/0ebHbaIDdZc/s1600/textnodesel.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="198" src="http://2.bp.blogspot.com/-2h0rj_IPJvI/Twn9dGkXptI/AAAAAAAAARI/0ebHbaIDdZc/s400/textnodesel.png" width="400" /></a></div>The output when <span style="font-family: "Courier New",Courier,monospace;">displayAttrs()</span> is called on the selected text node is shown here:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-T-wapB18UHc/Twn-FMOoapI/AAAAAAAAARQ/xFnswEWXmE4/s1600/isatextnode.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="136" src="http://3.bp.blogspot.com/-T-wapB18UHc/Twn-FMOoapI/AAAAAAAAARQ/xFnswEWXmE4/s400/isatextnode.png" width="400" /></a></div><br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com5tag:blogger.com,1999:blog-2909088349875842828.post-14464238447722928192012-01-08T15:02:00.001-05:002012-01-08T15:50:39.261-05:00Element Navigation Schematic<div dir="ltr" style="text-align: left;" trbidi="on">The following illustration shows the possible element properties for use in navigating the element tree in a structured document. All properties, with the exception of <span style="font-family: "Courier New",Courier,monospace;">HighestLevelElement </span>are those of the element shown in black. <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-Odtolba-r3Y/Twn2A5bVmzI/AAAAAAAAAQw/WPL9BFcmOxc/s1600/tree.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="270" src="http://4.bp.blogspot.com/-Odtolba-r3Y/Twn2A5bVmzI/AAAAAAAAAQw/WPL9BFcmOxc/s400/tree.png" width="400" /></a></div><br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-91786568690972455742012-01-08T12:29:00.000-05:002012-01-08T12:29:50.466-05:00Getting Attribute Names<div dir="ltr" style="text-align: left;" trbidi="on">Once you have an element's object, you can examine its attributes. This script lists the attributes of the currently selected element in the FrameMaker console.<br />
<br />
The script uses the <span style="font-family: "Courier New",Courier,monospace;">GetAttributes()</span> method and then iterates over the attribute list obtained, each time getting the name and writing that value to the FrameMaker Console. (The extra space prior to the name is used solely for readability purposes.)<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">// determines associated element definition name<br />
function getElementName(elem) {<br />
var elemDef, name = null;<br />
<br />
elemDef = elem.ElementDef;<br />
if (elemDef.ObjectValid()) {<br />
name = elemDef.Name;<br />
}<br />
return name;<br />
}<br />
<br />
//writes element name and list of attributes to the console<br />
function displayAttrs(elem) {<br />
var i, name, aName, attrs;<br />
<br />
name = getElementName(elem);</div><span style="font-family: "Courier New",Courier,monospace;"> Console(name);</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> attrs = elem.GetAttributes();</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> for (i = 0; i < attrs.len; i++) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> aName = attrs[i].name;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Console( " " + aName); </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> }</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">}</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">var doc, elem, eLoc, eRange;</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">doc = app.ActiveDoc;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">eRange = doc.ElementSelection;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">eLoc = eRange.beg;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">elem = eLoc.child;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">if (elem.ObjectValid()) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> displayAttrs(elem)</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">} else {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> Alert("No element was selected.",<br />
</span><span style="font-family: "Courier New",Courier,monospace;">Constants.FF_ALERT_CONTINUE_NOTE);</span><span style="font-family: "Courier New",Courier,monospace;"> </span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">}</span><br />
<br />
Consider the test case where the <span style="font-family: "Courier New",Courier,monospace;">oil.xml</span> document's <span style="font-family: "Courier New",Courier,monospace;">title </span>element is selected.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-2gpHvu9NsOM/TwnR2w4DNfI/AAAAAAAAAQg/sPQ0RUT1NUA/s1600/titlesel.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="198" src="http://4.bp.blogspot.com/-2gpHvu9NsOM/TwnR2w4DNfI/AAAAAAAAAQg/sPQ0RUT1NUA/s400/titlesel.png" width="400" /></a></div>The script produces the following output:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-j8ix6aswpVM/TwnSMxbNJXI/AAAAAAAAAQo/JK-zP0RyvyM/s1600/titleattrs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="297" src="http://1.bp.blogspot.com/-j8ix6aswpVM/TwnSMxbNJXI/AAAAAAAAAQo/JK-zP0RyvyM/s320/titleattrs.png" width="320" /></a></div><br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-13646333922784996842012-01-02T21:18:00.000-05:002012-01-02T21:18:44.645-05:00Getting an Element's Text<div dir="ltr" style="text-align: left;" trbidi="on">Once you know how to work with text, working with an element's text is straight-forward. The following function calls the element <span style="font-family: "Courier New",Courier,monospace;">GetText() </span>method asking for strings. It then iterates over any text items found and concatenates the values found into a single string.<br />
<br />
The <span style="font-family: "Courier New",Courier,monospace;">getElementText()</span> function is shown below. An example of its use will be provided in my next post.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">function getElementText(elem) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> var tItems, i, text = "";</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> tItems = elem.GetText(Constants.FTI_String);</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> for (i = 0; i < tItems.len; i += 1) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> switch (tItems[i].dataType) {</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> case Constants.FTI_String:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> text = text + tItems[i].sdata;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> break;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> }</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> }</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> return text;</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">}</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /></div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-19851628494218543972012-01-01T18:35:00.002-05:002012-01-01T18:35:00.567-05:00Collapsing Elements in the Structure View<div dir="ltr" style="text-align: left;" trbidi="on">Once you can access an element's object, you can affect how it is displayed in the structure view. <br />
<br />
By updating the <span style="font-family: "Courier New",Courier,monospace;">walkTree()</span> function with a single line of code, your script can collapse, as is the case here, or uncollapse elements in the tree. <br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">function walkTree(elem, count) {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> var child, name;</span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"> name = getElementName(elem);</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> <span style="color: red;">elem.ElementIsCollapsed = true;</span> // collapse element</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> Console(count + ": " + name);</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> child = elem.FirstChildElement; //get first child if any</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> while (child.ObjectValid()) {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> count = count + 1; //upate element count</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> count = walkTree(child, count); //traverse subtree with child root</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> child = child.NextSiblingElement; //get the siblings</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> }</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> return count;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> }</span><br />
<br />
Just be sure to redisplay the document when you are done to make your changes visible to the user.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">doc.Redisplay();</span><br />
<br />
Before the script was run, the structure view appears as follows:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-vF3QSY1JUeQ/Tv-e3G3ZKiI/AAAAAAAAAP0/C07A197avac/s1600/collapse.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-5WAcYcWMc40/Tv-eR0LPUwI/AAAAAAAAAPc/OJbVqBeF_HU/s1600/uncollapsed.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="247" src="http://1.bp.blogspot.com/-5WAcYcWMc40/Tv-eR0LPUwI/AAAAAAAAAPc/OJbVqBeF_HU/s320/uncollapsed.png" width="320" /></a></div>After the running the script, it appears as shown here:<br />
<br />
<br />
<a href="http://4.bp.blogspot.com/-vF3QSY1JUeQ/Tv-e3G3ZKiI/AAAAAAAAAP0/C07A197avac/s1600/collapse.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="109" src="http://4.bp.blogspot.com/-vF3QSY1JUeQ/Tv-e3G3ZKiI/AAAAAAAAAP0/C07A197avac/s320/collapse.png" width="320" /></a><br />
Just to verify that all elements in the tree were collapsed, I manually uncollapsed the root element to reveal that the script works as expected.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-9bmRpDhB-YQ/Tv-fVjDc-4I/AAAAAAAAAQA/Tg_9mem1bBo/s1600/rootuncollapsed.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="134" src="http://2.bp.blogspot.com/-9bmRpDhB-YQ/Tv-fVjDc-4I/AAAAAAAAAQA/Tg_9mem1bBo/s320/rootuncollapsed.png" width="320" /></a></div><br />
<br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-67618576459555344802011-12-22T17:46:00.000-05:002011-12-22T17:46:31.882-05:00Preorder Element Tree Traversal<div dir="ltr" style="text-align: left;" trbidi="on">Elements differ from other objects in a FrameMaker document in that they are organized not into a list but into a tree. The tree structure is exactly that you would see in the document's <b>Structure View</b> window.<br />
<br />
Typically, working with elements means starting with the highest level element in the structured flow, the root element, and visiting each of the elements in the tree in a predictable order.<br />
<br />
The algorithm described below uses a preorder traversal which visits the example element tree shown below in the order marked. <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-3JMwgR2Y2p4/TvOlYgZoTrI/AAAAAAAAAPE/dxvG5krInmE/s1600/depthfirst.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="317" src="http://1.bp.blogspot.com/-3JMwgR2Y2p4/TvOlYgZoTrI/AAAAAAAAAPE/dxvG5krInmE/s400/depthfirst.png" width="400" /></a><a href="http://1.bp.blogspot.com/-3JMwgR2Y2p4/TvOlYgZoTrI/AAAAAAAAAPE/dxvG5krInmE/s1600/depthfirst.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div><br />
<br />
The following script traverses the element tree using a recursive algorithm. The<span style="font-family: "Courier New",Courier,monospace;"> walkTree()</span> function starts at the root (or whatever node is passed in). It gets that node's children starting with the first child. It is obtained using the element property <span style="font-family: "Courier New",Courier,monospace;">FirstChildElement</span>.<br />
<br />
After processing that element, <span style="font-family: "Courier New",Courier,monospace;">walkTree()</span> calls itself this time passing in the child element. When that branch of the tree is processed, it continues on seeking any sibling elements using the element property <span style="font-family: "Courier New",Courier,monospace;">NextSiblingElement</span>.<br />
<br />
<b>NOTE:</b> While not strictly necessary, the script keeps track of the element count to help make the association with the element numbers shown in the example above.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">// Determines associated element definition name<br />
function getElementName(elem) {<br />
var elemDef, name = null;<br />
<br />
elemDef = elem.ElementDef;<br />
if (elemDef.ObjectValid()) {<br />
name = elemDef.Name;<br />
}<br />
return name;<br />
}<br />
<br />
//Recursively traverses element tree in preorder fashion<br />
function walkTree(elem, count) {<br />
var child, name;<br />
<br />
name = getElementName(elem);<br />
Console(count + ": " + name);<br />
child = elem.FirstChildElement; //get first child if any<br />
while (child.ObjectValid()) {<br />
count = count + 1; //upate the element count to reflect element found<br />
count = walkTree(child, count); //traverse subtree with child root<br />
child = child.NextSiblingElement; //get the siblings<br />
}<br />
return count;<br />
}<br />
<br />
var doc, flow, root;<br />
<br />
doc = app.ActiveDoc;<br />
flow = doc.MainFlowInDoc;<br />
root = flow.HighestLevelElement;<br />
if (root.ObjectValid()) {<br />
walkTree(root, 1);<br />
}</div><br />
The script output appears in the FrameMaker console and is shown here:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-I64MPEaQGMI/TvOybwvLauI/AAAAAAAAAPQ/GGfQacRBp5M/s1600/element+order.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="199" src="http://4.bp.blogspot.com/-I64MPEaQGMI/TvOybwvLauI/AAAAAAAAAPQ/GGfQacRBp5M/s320/element+order.png" width="320" /></a></div><br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com1tag:blogger.com,1999:blog-2909088349875842828.post-3873304709319096922011-12-20T20:02:00.000-05:002011-12-20T20:02:36.147-05:00Determing What Element is Selected (Part 2)<div dir="ltr" style="text-align: left;" trbidi="on">This post looks at the same element selections used in the previous post but this time, it is the end of the element selection that is of interest. Adapting<span style="font-family: "Courier New",Courier,monospace;"> getElementSelectionStart()</span> is straight-forward as shown here:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">function getElementSelectionEnd(doc) {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> var eLoc, eRange, locInfo;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> eRange = doc.ElementSelection;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> locInfo = {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 'parent' : eRange.end.parent,</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 'child' : eRange.end.child,</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> 'offset' : eRange.end.offset</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> };</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> return locInfo;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">}</span><br />
<br />
In the case where the root element is selected, the parent element end is <span style="font-family: "Courier New",Courier,monospace;">null </span>and the child is <span style="font-family: "Courier New",Courier,monospace;">null </span>and the offset is <span style="font-family: "Courier New",Courier,monospace;">0</span>. This makes sense as selecting the root element is equivalent to selecting the whole flow. There are no elements beyond that point. <br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-MEllRXXooeA/TvErPnwckEI/AAAAAAAAAOc/dn-x7DCJYLY/s1600/allnull.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="175" src="http://2.bp.blogspot.com/-MEllRXXooeA/TvErPnwckEI/AAAAAAAAAOc/dn-x7DCJYLY/s400/allnull.png" width="400" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-s1P0tKx6StY/Tu_Rum1K9JI/AAAAAAAAAOU/KW4p8sp67YQ/s1600/concept%2527.png" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><br />
If an element other than the root element is selected and that element has no sibling following, the end <i>child </i>is <span style="font-family: "Courier New",Courier,monospace;">null </span>because its location is just beyond the last character in the selected element. The <i>parent </i>is the parent of the selected element. <br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-ZAeUS517a1E/Tu_NXj_cV6I/AAAAAAAAAN0/sD7Iyy2nZ48/s1600/concept%2527.png" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-qkOmI21lt2c/TvErw7RGYKI/AAAAAAAAAOk/l4ORvvqm4Zg/s1600/parentlink.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="http://4.bp.blogspot.com/-qkOmI21lt2c/TvErw7RGYKI/AAAAAAAAAOk/l4ORvvqm4Zg/s400/parentlink.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-CTyyjxjy_uQ/Tu_RmaVCyEI/AAAAAAAAAOM/IVt4w5dGvqk/s1600/linktext.png" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><br />
In the case where the <b>title </b>element is selected there is a child element at the end of the selection as <b>title </b>has a "younger" sibling <b>prolog</b>. <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-y9ic3Toa_Ag/TvEtu04PrMI/AAAAAAAAAO0/ERsfq8QD3ZM/s1600/titleelem.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="176" src="http://3.bp.blogspot.com/-y9ic3Toa_Ag/TvEtu04PrMI/AAAAAAAAAO0/ERsfq8QD3ZM/s400/titleelem.png" width="400" /></a></div><br />
This third example has an insertion point between the "o" and the "t" in "Motor" in the first document paragraph. In this case, the end <i>parent </i>element is <b>p </b>(the paragraph element), and there is no child element. The <i>offset </i>from the start of <b>p </b>is 2. This is exactly the same as was the case with the start element location as with an insertion point, as with an insertion point the starting and ending locations are the exactly same.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-cPf_vgFVF5I/TvEsc363SNI/AAAAAAAAAOs/JnyZ8cJYg9k/s1600/parentisp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="178" src="http://3.bp.blogspot.com/-cPf_vgFVF5I/TvEsc363SNI/AAAAAAAAAOs/JnyZ8cJYg9k/s400/parentisp.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-mCrc6pxJpCM/Tu_QsiTqzmI/AAAAAAAAAOE/S8oMB7dz6XY/s1600/offset2.png" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-Jm5t1Wi8ce4/Tu_OtuPxjsI/AAAAAAAAAN8/-7xzSRd8LCI/s1600/offset2.png" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com2tag:blogger.com,1999:blog-2909088349875842828.post-87088090889198569292011-12-19T19:16:00.000-05:002011-12-19T19:16:39.452-05:00Determining What Element is Selected (Part 1)<div dir="ltr" style="text-align: left;" trbidi="on">Element selections are a similar to text selections in some ways but differ in others.<br />
<br />
Use the document property <span style="font-family: "Courier New",Courier,monospace;">ElementSelection </span>to get the current element selection.<br />
<br />
Just as text selections consist of a <i>text range </i>with beginning and ending <i>text </i>locations, element selections are an <i>element range </i>with beginning and ending <i>element</i> locations.<br />
<br />
The difference between the two emerges when you look at the element locations that define the starting and ending points for an element selection. Unlike a text location which is typically a paragraph and an offset from the start of that paragraph, an element location <span style="font-family: "Courier New",Courier,monospace;"></span>consists of:<br />
<ul style="text-align: left;"><li>A parent element</li>
<li>A child element </li>
<li>An offset which is relative to the containing element.</li>
</ul>The following script demonstrates how to work with the beginning of an element selection. It can also be used as a tool for understanding the meaning of parent and child element in this context.<br />
<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">//Returns the element definition name</div><div style="font-family: "Courier New",Courier,monospace;">function getElementName(elem) {<br />
var elemDef, name = null;<br />
<br />
elemDef = elem.ElementDef;<br />
if (elemDef.ObjectValid()) {<br />
name = elemDef.Name;<br />
}<br />
return name;<br />
}</div><div style="font-family: "Courier New",Courier,monospace;"><br />
</div><div style="font-family: "Courier New",Courier,monospace;"></div><div style="font-family: "Courier New",Courier,monospace;">//Returns location information for the current element selection<br />
function getElementSelectionStart(doc) {<br />
var eLoc, eRange, locInfo;<br />
eRange = doc.ElementSelection;<br />
locInfo = {<br />
'parent' : eRange.beg.parent,<br />
'child' : eRange.beg.child,<br />
'offset' : eRange.beg.offset<br />
};<br />
return locInfo;<br />
}<br />
<br />
var doc, elem, pName = null, cName = null, locInfo;<br />
doc = app.ActiveDoc;<br />
<br />
locInfo = getElementSelectionStart(doc);<br />
<br />
if (locInfo.parent.ObjectValid()) {<br />
pName = getElementName(locInfo.parent);<br />
}<br />
if (locInfo.child.ObjectValid()) {<br />
cName = getElementName(locInfo.child);<br />
}<br />
Alert("Parent is " + pName + ", child is " + cName + " and offset is " + locInfo.offset,<br />
Constants.FF_ALERT_CONTINUE_NOTE);</div><br />
The first two test shown deal with the case where an entire element is selected. In these cases, the offset from the start of the element is always 0. <br />
<br />
In the case where the root element is selected, the <i>parent </i>element is null and the <i>child </i>is the root element:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-s1P0tKx6StY/Tu_Rum1K9JI/AAAAAAAAAOU/KW4p8sp67YQ/s1600/concept%2527.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="218" src="http://1.bp.blogspot.com/-s1P0tKx6StY/Tu_Rum1K9JI/AAAAAAAAAOU/KW4p8sp67YQ/s400/concept%2527.png" width="400" /></a></div><br />
If an element other than the root element is selected, the <i>child </i>is the selected element and the <i>parent </i>is the parent of that child element.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-ZAeUS517a1E/Tu_NXj_cV6I/AAAAAAAAAN0/sD7Iyy2nZ48/s1600/concept%2527.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-CTyyjxjy_uQ/Tu_RmaVCyEI/AAAAAAAAAOM/IVt4w5dGvqk/s1600/linktext.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="195" src="http://4.bp.blogspot.com/-CTyyjxjy_uQ/Tu_RmaVCyEI/AAAAAAAAAOM/IVt4w5dGvqk/s400/linktext.png" width="400" /></a></div><br />
This final example has an insertion point between the "o" and the "t" in "Motor" in the first document paragraph. In this case, the <i>parent </i>element is <b>p </b>(the paragraph element), and there is no child element. The <i>offset </i>from the start of <b>p </b>is 2.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-mCrc6pxJpCM/Tu_QsiTqzmI/AAAAAAAAAOE/S8oMB7dz6XY/s1600/offset2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="http://2.bp.blogspot.com/-mCrc6pxJpCM/Tu_QsiTqzmI/AAAAAAAAAOE/S8oMB7dz6XY/s400/offset2.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-Jm5t1Wi8ce4/Tu_OtuPxjsI/AAAAAAAAAN8/-7xzSRd8LCI/s1600/offset2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br />
</a></div><br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0tag:blogger.com,1999:blog-2909088349875842828.post-2052724332109619542011-12-17T13:01:00.002-05:002011-12-17T15:37:42.328-05:00Getting an Element's Definition Name<div dir="ltr" style="text-align: left;" trbidi="on">When working with elements, it can be important to know an element's definition name. If you start with an element, you need to:<br />
<ol style="text-align: left;"><li>Get the associated element definition.</li>
<li>Get the definition name. </li>
</ol><b>NOTE: </b>A FrameMaker flow's element tree includes text nodes that do not have associated definitions and therefore have no name.<br />
<br />
The following script displays the definition name of the highest level element in the main flow.<br />
<br />
<b>NOTE: </b>The name returned is that in the EDD rather than in your DTD or schema. <br />
<br />
f<span style="font-family: "Courier New",Courier,monospace;">unction getElementName(elem) {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> var elemDef, name = null;</span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"> elemDef = elem.ElementDef;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> if (elemDef.ObjectValid()) {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> name = elemDef.Name;</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> }</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> return name;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">}</span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">var doc, flow, root, name;</span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">doc = app.ActiveDoc;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">flow = doc.MainFlowInDoc;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">root = flow.HighestLevelElement;</span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">if (root.ObjectValid()) {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> name = getElementName(root);</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> if (name !== null) {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> Alert(name, Constants.FF_ALERT_CONTINUE_NOTE);</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> } else {</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> Alert("Text node", Constants.FF_ALERT_CONTINUE_NOTE);</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> }</span><br />
<span style="font-family: "Courier New",Courier,monospace;">}</span><br />
<div style="font-family: "Courier New",Courier,monospace;"><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-zrB1sevIjeY/TuzYkZUcGoI/AAAAAAAAANk/9ETT6bsexvc/s1600/concept%2527.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="222" src="http://4.bp.blogspot.com/-zrB1sevIjeY/TuzYkZUcGoI/AAAAAAAAANk/9ETT6bsexvc/s400/concept%2527.png" width="400" /></a></div><br />
</div><div class="blogger-post-footer">W9ACUGJMJ4Y9</div>Debra Hermanhttp://www.blogger.com/profile/16336331080547778765noreply@blogger.com0