8 Replies Latest reply on Oct 14, 2013 7:35 PM by Marc Autret

    How to extend/add additional functionality (to) an InDesign class like Cell

    R.A.A

      Hello,

      I am trying to add some extra functionality to every instance of e.g. the Cell 'class' of InDesign using Javascript. I started doing something like this:

       

      Cell.prototype.newFunction = function() { ....... }

       

      which works fine: it is now possible to call newFunction() on every instance of Cell.

      But now I would like to let this function (that I've added to the prototype chain of Cell like shown above and thus is also available for an 'instance' of Cell) use a 'variable' that is specific for every Cell instance, e.g.:

        

      Cell.prototype.getSuperValue = function ()

      {

      if (this._cachedValue === undefined)

      {

      this._cachedValue = 3; // doing some incredible calculations that take some time

      }

      return this._cachedValue;

      };

        

      The this._cachedValue should be a attribute of the Cell instance. So if I take to cells from a Table and I call getSuperValue() on them I can get two different values that are specific for every instance of Cell.

       

        

      Thanks a lot in advance!

       

        

      P.S. although I am quite new to Javascript I know there are no classes in Javascript and that Cell is an object. But I thought explaining it like this would make it more clear?

        • 1. Re: How to extend/add additional functionality (to) an InDesign class like Cell
          John Hawkinson Level 5

          The implication is that you've tried it and it does not actually work.

          But you don't actually say that?

           

          So what exactly is the problem or behavior you are seeing?

           

          (I would sort of expect this not to work very well with InDesign DOM objects, because they don't behave like normal Javascript objects all of the time. But you might be lucky.)

          • 2. Re: How to extend/add additional functionality (to) an InDesign class like Cell
            R.A.A Level 1

            Oops yes it indeed doesn't do the job. When I have a reference to an object/instance of Cell and I try for example:

             

            cell.newValue = 3;

             

            where cell is a reference to the instance it gives the error:

             

            Error: Object does not support the property or method 'newValue'.

             

             

            I also suspected something like you said (these InDesign DOM objects having different behaviour than 'standard' Javascript objects) but I have too little InDesign and Javascript knowledge to be 100% sure that this is the cause of the problem.

            • 3. Re: How to extend/add additional functionality (to) an InDesign class like Cell
              John Hawkinson Level 5

              Yeah, I don't think that's going to work for you.

              But you could cheat and store the data in an array indexed by cell id, something like (untested):

               

              Cell.prototype.getSuperValue = function () {
                var CellCache = [];
                if (cellCache[this.id] === undefined) {
                  cellCache[this.id] = 3; // doing some incredible calculations that take some time
                }
                return cellCache[this.id];
              };
              

               

              I don't know if inheritance is going to screw it up for you and maybe you want to index by this.toSpecifier().

              And maybe using a sparse array is a bad idea and you should use an Object instead, i.e. var cellCache = {};

              1 person found this helpful
              • 4. Re: How to extend/add additional functionality (to) an InDesign class like Cell
                Marc Autret Level 4

                As John said, DOM objects have different behaviour than pure JS objects. More precisely, DOM objects are just syntactic specifiers that encapsulate commands, they don't actually give you read-and-write access to the final InDesign components. For example, what you call an 'instance' of the Cell object just represents a command, which may or may not point out to one, or several, actual InDesign cell(s). So when you extend the prototype of such object, you simply 'decorate' the interface of that command, but this has no impact on actual document cells:

                 

                Cell.prototype.myProperty = 1;
                Cell.prototype.myMethod = function(){ alert('foo'); };
                
                // individual specifier:
                alert( myTable.cells[0].myProperty );           // => 1
                
                // collective specifier:
                alert( myTable.cells.everyItem().myProperty );     // => 1!
                
                // individual specifier:
                myTable.cells[0].myMethod();               // => 'foo'
                
                // collective specifier:
                myTable.cells.everyItem().myMethod();          // => 'foo' (once!)
                

                 

                In the example above, myProperty and myMethod() does not extend cell's interface in terms of component's interface. This syntactically works as long as you don't attempt to write data within the real cell component (which you cannot extend):

                 

                myTable.cells[0].myProperty = 2; // ERROR: myProperty is not supported!
                

                 

                That said, ExtendScript provide a way to store data in most of the components through the label property. In your project, you probably could serialize your data and use Cell.label to manage it.

                 

                @+

                Marc

                • 5. Re: How to extend/add additional functionality (to) an InDesign class like Cell
                  Harbs. Level 6

                  Just agreeing with John and Marc, that you do not want to be using native objects the way you are.

                   

                  John's method of using ids is not great, because the id of a cell is its coordinates, so the id is not unique across different tables.

                   

                  Using Cell.label (or better yet (Cell.insertLabel() and Cell.extractLabel()) is the way to go...

                   

                  Harbs

                  1 person found this helpful
                  • 6. Re: How to extend/add additional functionality (to) an InDesign class like Cell
                    R.A.A Level 1

                    Hi John, Harbs and Marc,

                     

                    Thanks a lot for the helpful information!

                     

                    One of the things I was trying to do is give the 'instance of Cell' extra functionality like obtaining geometric information of that cell, e.g. getInsideArea which would return a rectangle containing the position and size of that cell. I wanted to give the cell a reference to an Javascript object that contained geometric information of the Table the cell is in. This geometric information is used by me to obtain the cell geometric information.

                     

                    Again thanks a lot!

                    • 7. Re: How to extend/add additional functionality (to) an InDesign class like Cell
                      McShaman Level 1

                      Marc, does this same issue extend to scriptUI objects?

                      • 8. Re: How to extend/add additional functionality (to) an InDesign class like Cell
                        Marc Autret Level 4

                        > does this same issue extend to scriptUI objects?

                         

                        Not at all in the sense discussed above. ScriptUI objects are not part of the DOM, they are not specifier-based, and they basically allow prototypal extension in a number of (very interesting) ways. Unfortunately there are specific issues in that field too—and most are incomprehensible to me.

                         

                        @+

                        Marc