John Steam February 2016

How can I use higher order functions like Array.reduce() in an Indesign script?

I've started a project where I need to use Adobe Indesign and ExtendScript to programmatically extract some data from a series of INDD files. The version of Javascript used for scripting in these programs doesn't support any of the higher order functions that I'm used to using (Array.reduce(), Array.forEach(), Array.map(), etc...).

Is there a way to add this functionality to ExtendScript? I feel like I'm walking around in a room with a four foot high ceiling.

Answers


John Steam February 2016

Use a Polyfill

ExtendScript appears to support prototyping of pure Javascript objects (but not Indesign DOM objects), so it is possible to use a polyfill to add missing functionality. Polyfill code can be found on MDN on the page for the method in question under "Polyfill". Here's an example: MDN Array.prototype.reduce() Polyfill. There are polyfills for numerous methods, including Array.map(), Array.indexOf(), Array.filter(), and Array.forEach().

To implement the code, just create an appropriately named file (ie, polyfill.js or reduce.js) in the same folder as your script. Copy the polyfill code from MDN into the file you just created, like so:

// Production steps of ECMA-262, Edition 5, 15.4.4.21
// Reference: http://es5.github.io/#x15.4.4.21
if (!Array.prototype.reduce) {
  Array.prototype.reduce = function(callback /*, initialValue*/) {
    'use strict';
    if (this == null) {
      throw new TypeError('Array.prototype.reduce called on null or undefined');
    }
    if (typeof callback !== 'function') {
      throw new TypeError(callback + ' is not a function');
    }
    var t = Object(this), len = t.length >>> 0, k = 0, value;
    if (arguments.length == 2) {
      value = arguments[1];
    } else {
      while (k < len && !(k in t)) {
        k++; 
      }
      if (k >= len) {
        throw new TypeError('Reduce of empty array with no initial value');
      }
      value = t[k++];
    }
    for (; k < len; k++) {
      if (k in t) {
        value = callback(value, t[k], k, t);
      }
    }
    return value;
  };
}

Then add the following line at the beginning of your script, replacing the filename appropriately:


              

milligramme February 2016

I use underscore.js instead.

Underscore.js http://underscorejs.org/

#include '/path-to/underscore.js'
var _ = this._;

adding this snippet at the beginning of the script.

thank you

mg.

Post Status

Asked in February 2016
Viewed 1,674 times
Voted 8
Answered 2 times

Search




Leave an answer