4 Replies Latest reply on Nov 4, 2012 11:40 AM by jaloren28

    Declaring Variables

    Jason L-S Level 1

      This is a pretty basic question. How do you know when to declare a variable as new object, and when to simply declare it by naming it?


      For example, here is a list of variables:


      var textRange = new TextRange();

      var pgf;


      The textRange variable is declared as a new TextRange object. But the pgf variable is not declared as a new Pgf object. If you try to do this, ExtendScript says, "Pgf does not have a constructor."


      How do you know if an object has a constructor? I see in the scripting guide that the TextRange object also lists TextRange as a method. That might be a clue, right?


      Also, is it important to declare a variable as new object if it does have a constructor? For example, is there a difference between these two declarations:


      var textRange;

      var textRange = newTextRange();


      Or is it more-or-less a preference?





        • 1. Re: Declaring Variables
          jaloren28 Level 2

          Hi Jason, 


          Constructors are a special type of object in javascript. Think of them as like a blueprint for an object that any instance of that object is based off. See here for an intro to that: 




          However, I don't think that's relevant to your question. What you are talking about is undefined variables. If the first instance of the variable, is like this:


          var varname;


          And I don't assign a value to the variable, then the variable is undefined. In other words, the variable has no value. So if you attempted to use that variable in a method or a function, then it is 99% likely that the function will not work as expected because the variable has no value and thus nothing for the function to use.


          In JavaScript (or in any language for that matter), its usually considered a really bad idea to have undefined variables in your code. A variable is a container that holds data. You use variables as a mechanism to point to the data you want the script to work on. If the container is empty, then the script is likely to have problems processing non-existent data .


          My understanding is that some programmers like to enumerate a specific list of variables that they will use throughout their program and then initialize them (.i.e assign data) later on the in the code. However, if you aren't careful, you could end up with all sorts of unexpected behavior. My recommendation is to always initialize your variables.



          • 2. Re: Declaring Variables
            Jason L-S Level 1

            Thanks Joe.


            I see that undeclared variables are a bad idea. I think what you're saying is that Javascript doesn't care whether you declare your variables first before assigning a value to it. So up front declarations are not a requirement, and could actually cause errors, right?


            Anyway, I guess my question is more specific to ExtendScript an FrameMaker objects.


            Take a look at Deb Herman's blog entry on setting a text location.



            Notice how she wrote:

            var tLoc= new TextLoc(); //create the text location object


            Instead of something like:

            var tLoc;

            tLoc.obj = pgf; //make it a paragraph


            That wouldn't work. You get, "Undefined. Is not an object."


            Yet you don't have to declare the pgf variable as a Paragraph object before setting it to the first paragraph in the main flow. For example:


            var mainflow = doc.MainFlowInDoc;

            var tframe = mainflow.FirstTextFrameInFlow;

            var pgf = tframe.FirstPgf;


            You could not write:


            var mainflow = doc.MainFlowInDoc;

            var tframe = mainflow.FirstTextFrameInFlow;

            var pgf = new Pgf();

            pgf = tframe.FirstPgf;


            You get, "Pgf does not have a constructor."


            So back to the question. How do you know which objects in FrameMaker have constructors?





            • 3. Re: Declaring Variables
              Ian Proudfoot Adobe Community Professional

              One of the easiest ways to see if a constructor is required is to look at the Types panel in the ExtendScript Object Model Viewer.

              Regarding the declaration of Variables, JavaScript really benefits from declaring variables at the begining of a function. It's easier to maintain and makes it easier to remember that JavaScript variables do not have block scope. If you do not declare your variables before they are used JavaScript assumes they are global, which may not be what you want and too many global variables gets messy and can cause interferrence between Scripts.


              I have found it really useful to check my ExtendScript code with JSLint http://www.jslint.com/.



              • 4. Re: Declaring Variables
                jaloren28 Level 2

                Hi Jason, 


                Your question is getting into the Document Object Model (DOM) that FrameMaker uses.   Everything in JavaScript is an object. An object is a special type of data that has properties and methods. For example, a String object in javascript contains string data AND has methods for doing regex searches on the string.   There's a difference between built-in objects and user-defined objects. In JavaScript itself, the language has several built-in objects, such as Date and String, that anyone can use. Anyone who is familiar with JavaScript knows what those are.


                On top of JS itself, a JavaScript API can have its own set of built-in objects. A key difference between built-in objects versus user-defined objects is the control that you as the programmer have over them. A built-in object is something that already exists and has its own set of rules built into it because it was built into the language via the API you are using. You, as the programmer, must abide by those rules in order to use the object. By contrast, a user-defined object is defined by the programmer and as such the object can be and do whatever you want as long as it abides by the high level rules of JS and the DOM you are working in.


                ExtendScript is a JavaScript API for the FrameMaker DOM. In order to know how to create and use these objects, you usually have to refer to the vendor's API documentation and understand where the object is located in the DOM. In FrameMaker's DOM (or any DOM for that matter), you have a hierarchical relationship between objects. With the exception of global and app every other object is a child of some other object. The parent object usually imposes specific constraints on using the child object. Here's my crude representation of the DOM, which contains the paragraph object. 



                   app (this is the framemaker application and would be different if you were in RoboHelp for example)




                Also, note that paragraph object could be further down the DOM depending on what type of paragraph object you are talking about (text frames and flows are annoying). So if you wanted the first paragraph in the main flow of the doc it would be like this



                   app (this is the framemaker application and would be different if you were in RoboHelp for example)



                              text frame



                So once you isolate the object in the DOM, then you can learn about that object. Let's take the two built-in objects you mentioned.


                • Textloc
                • Pgf


                Your quesiton is: how do i create these objects? And the answer is: however the API tells you to. Or in other words, what does the vendor's API documentation tell you? Now I know that's a poor response cause Adobe's Extenscript documentation is absolutely atrocious. But we'll try do this anyway using their ExtendScript guide.


                If you look up the paragraph object, you will see that there is no method to add a new paragraph. The next step then is to see if the parent object does give you the capability to do that. Since the parent object is document, you should look at the document's methods. And guess what it turns out there is just such a method: NewSeriesPgf.  So if you wanted to add a new paragraph to a document, you'd have something like this:


                var doc = app.ActiveDoc;
                var prevPgf=doc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;
                var newPgf=doc.NewSeriesPgf(prevPgf)


                A TextLoc object is a special built-in object that allows you to find a particular text location in a document. With a text loc you can find and replace text or even modify text if you want. Because of the nature of this object, a user may need an indeterminate number of them since every single point in the document could be a text location object. So instead of using a method to create a text loc object, a user just creates the object and then uses it.  Manipulating text via ExtendScript is one of the most complicated and confusing things to do and there are all sorts of non-obvious things about the DOM you need to understand to do it correctly.


                Hope that helps.