Skip to main content
frameexpert
Community Expert
Community Expert
December 7, 2012
Answered

ExtendScript libraries

  • December 7, 2012
  • 3 replies
  • 11235 views

Hello All,

I want to create a library of commonly used functions, etc. that I can use in my ExtendScript scripts. I created a script that I put in the JavaScript startup folder that has this content:

var CPF = {};

CPF.getText = function () {

   

    var text = "";

    return {

        getText: function (textObj) {

            // Get a list of strings in the text object.

            var textItems = textObj.GetText(Constants.FTI_String);

            // Concatenate the strings.

            for (var i = 0; i < textItems.len; i += 1) {

                text += (textItems.sdata);

            }

        }

    };

}

Now when I want to get the text of a text object, I can use this:

alert (CPF.getText(pgf)); // pgf is a paragraph.

One important note: I am using ExtendScript with FrameMaker here, not InDesign, so the code itself may look unfamiliar. I am posting here because the principles should be the same in InDesign and there are a lot of smart people here :-). I have been looking at JavaScript libraries and reading about good design patterns, but I am having a hard time translating this to the ExtendScript environment.

My questions are: Is this the best way to do this kind of thing? Or, is there a better way to have a library of functions that can be used in my scripts? Thanks in advance.

Rick

This topic has been closed for replies.
Correct answer Marc Autret

Hi Rick,

Here is the general design pattern I use for any library or sublibrary I create in ExtendScript:

$.global.hasOwnProperty('MyLibrary')||(function(HOST, SELF)

{

    HOST[SELF] = SELF;

    // =================================

    // PRIVATE

    // =================================

    var INNER = {};

    INNER.myPrivateData1 = "foo";

    INNER.myPrivateFunc1 = function(){ /* . . . */ };

    /* . . . */

    // =================================

    // API

    // =================================

    SELF.myPublicData1 = 123;

    SELF.myPublicMethod1 = function(){ alert(INNER.myPrivateData1); };

    /* . . . */

})($.global,{toString:function(){return 'MyLibrary';}});

// Usage

// ---

MyLibrary.myPublicMethod1();

I came up with that general structure after a number of tries and approaches. This one is the most convenient to me for several reasons:

• It supports persistent engines (i.e. does not uselessly re-create the library from scratch).

• It supports to be included, and still works as jsxbin.

• The body uses a single 'closure' variable (INNER), where I can load any required private data or func.

• The same pattern can be used to include a submodule within an existing one: just adjust the HOST argument to your needs.

• I can change the name of a library very easily: just replace the two occurences of 'MyLibrary' by the new name.

• Finally, that pattern is very generic and uniform (based on HOST, SELF and INNER). All modules I've written so far are now implemented this way: DOM helpers, ScriptUI stuff, data manipulation, and so on.

@+

Marc

3 replies

Inspiring
March 29, 2017

Excellent Marc - just what I was looking for !!In my version. I put the various my* declarations and the call to /MyLibrary.myPublicMethod1();   in a comment, so that I can since I invariably forget to remove them......

Marc Autret
Marc AutretCorrect answer
Legend
December 8, 2012

Hi Rick,

Here is the general design pattern I use for any library or sublibrary I create in ExtendScript:

$.global.hasOwnProperty('MyLibrary')||(function(HOST, SELF)

{

    HOST[SELF] = SELF;

    // =================================

    // PRIVATE

    // =================================

    var INNER = {};

    INNER.myPrivateData1 = "foo";

    INNER.myPrivateFunc1 = function(){ /* . . . */ };

    /* . . . */

    // =================================

    // API

    // =================================

    SELF.myPublicData1 = 123;

    SELF.myPublicMethod1 = function(){ alert(INNER.myPrivateData1); };

    /* . . . */

})($.global,{toString:function(){return 'MyLibrary';}});

// Usage

// ---

MyLibrary.myPublicMethod1();

I came up with that general structure after a number of tries and approaches. This one is the most convenient to me for several reasons:

• It supports persistent engines (i.e. does not uselessly re-create the library from scratch).

• It supports to be included, and still works as jsxbin.

• The body uses a single 'closure' variable (INNER), where I can load any required private data or func.

• The same pattern can be used to include a submodule within an existing one: just adjust the HOST argument to your needs.

• I can change the name of a library very easily: just replace the two occurences of 'MyLibrary' by the new name.

• Finally, that pattern is very generic and uniform (based on HOST, SELF and INNER). All modules I've written so far are now implemented this way: DOM helpers, ScriptUI stuff, data manipulation, and so on.

@+

Marc

frameexpert
Community Expert
Community Expert
December 8, 2012

Fantastic, Marc, thank you very much!

Do you recommend using "include" or putting it in the startup folder? Thanks.

Rick

Marc Autret
Legend
December 9, 2012

frameexpert wrote:

Do you recommend using "include" or putting it in the startup folder? Thanks.

Rick

It depends on what you are doing. Personnaly I tend to avoid loading startup scripts unless there is a serious reason to (e.g. menu manager).

@+

Marc

Peter Kahrel
Community Expert
Community Expert
December 7, 2012

You could include your libraries:

#include mylibrary.jsx

Peter

frameexpert
Community Expert
Community Expert
December 7, 2012

Hi Peter,

Thanks for your reply. I was asking more about how to structure the library and functions, and how to call them. Also, if I put them in the startup folder, then I shouldn't have to include them. Thanks.

Rick