Skip to main content
frameexpert
Community Expert
Community Expert
Dec 7, 2012 1:21 PM UTC
Answered

ExtendScript libraries

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 is closed to new replies. Start a new post to keep the conversation going.
Marc Autret
Marc AutretCorrect answer
Legend
Dec 8, 2012 4:42 PM UTC

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

22 replies

Inspiring
Mar 29, 2017 8:40 AM UTC

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......

Translate
Marc Autret
Marc AutretCorrect answer
Legend
Dec 8, 2012 4:42 PM UTC

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

Translate
frameexpert
Community Expert
Community Expert
Dec 8, 2012 5:49 PM UTC

Fantastic, Marc, thank you very much!

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

Rick

Translate
www.frameexpert.com
Marc Autret
Legend
Dec 9, 2012 1:53 PM UTC

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

Translate
Peter Kahrel
Community Expert
Community Expert
Dec 7, 2012 2:11 PM UTC

You could include your libraries:

#include mylibrary.jsx

Peter

Translate
frameexpert
Community Expert
Community Expert
Dec 7, 2012 5:51 PM UTC

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

Translate
www.frameexpert.com