.indexOf is not a function :(

Advocate ,
May 18, 2017 May 18, 2017

Copy link to clipboard

Copied

Hi there,

im struggeling with this simple task:

var myAlphas = image.clippingPath.alphaChannelPathNames;

var AlphaIndex = myAlphas.indexOf("our_default");

…because even this example doesnt work:

var fruits = ["Banana", "Orange", "Apple", "Mango"];

var a = fruits.indexOf("Apple");

alert(a);

from JavaScript Array indexOf() Method

All I get is
Bildschirmfoto 2017-05-18 um 15.11.15.png
and since Im more of a designer than a scripter, i cant solve that by myslef. Someone to the rescue?

TOPICS
Scripting

Views

21.9K

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

LEGEND , May 18, 2017 May 18, 2017

It's not entirely DBLJan's mistake Look here: indexOf Method (Array) (JavaScript) | Microsoft Docs  -- it is supported in JavaScript!

But the problem is that InDesign's JavaScript engine is out of date (*). This particular construction did not exist at the time when Adobe implemented it, and nowadays your everyday updated browser properly supports it because they were updated.

(*) It's even so out of date that technically we should not be calling it "JavaScript" at all. The ESTK gets that part r

...

Likes

Translate

Translate
Valorous Hero ,
May 18, 2017 May 18, 2017

Copy link to clipboard

Copied

Hi,

You have to understand that javascript objects have specific properties and methods. Most of the time you can't call a method of some object A to object B is they don't share this same method (dramatically shortening things here).

In your case, indexOf is a method of a String object while myAlphas is an array. An array object doesn't have a indexOf method, hence your error message.

In short, you are talking wrong to the buddy.

Something like this should work (not tested).

var myAlphas = image.clippingPath.alphaChannelPathNames;

var reg = new RegEx ( "("+["Banana", "Orange", "Apple", "Mango"].join("|")+")$", "");

var n = myAlphas.length;

while ( n-- ) {

  if ( reg.test ( myAlphas ) ) {

  alert( "Gotcha" );

  break;

  }

}

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
May 18, 2017 May 18, 2017

Copy link to clipboard

Copied

It's not entirely DBLJan's mistake Look here: indexOf Method (Array) (JavaScript) | Microsoft Docs  -- it is supported in JavaScript!

But the problem is that InDesign's JavaScript engine is out of date (*). This particular construction did not exist at the time when Adobe implemented it, and nowadays your everyday updated browser properly supports it because they were updated.

(*) It's even so out of date that technically we should not be calling it "JavaScript" at all. The ESTK gets that part right: it's properly called "ExtendScript".

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
May 18, 2017 May 18, 2017

Copy link to clipboard

Copied

My bad indeed

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 18, 2017 May 18, 2017

Copy link to clipboard

Copied

Phew, i was going mad, why this shouldnt work, …since it was an example direct from the w3school.
Also, as i mentioned, im no trained coder, but I get better at code-snippet-tetris by every script

As I should have done before I posted this, I haved used the searchforum feature to find this post, suggesting adding this snippet to my code:

Array.prototype.indexOf = function ( item ) {

          var index = 0, length = this.length;

          for ( ; index < length; index++ ) {

                    if ( this[index] === item )

                              return index;

          }

          return -1;

          };

And guess what – it works perfectly. Because after all I only was looking for a way to find something in my array of (…and here I often dont know what im getting, I do best working with strings) values.

But thank you Loic.Aigon for the deep insights!

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jul 20, 2022 Jul 20, 2022

Copy link to clipboard

Copied

LATEST

@DBLjan 

Thanks, this solution works for me and saves me quite some hustle

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
May 18, 2017 May 18, 2017

Copy link to clipboard

Copied

Just include prototype definitions:

German site, source commends English, download requires registration and login

JavaScriptClassEnhancements for JavaScript Array Class

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
May 18, 2017 May 18, 2017

Copy link to clipboard

Copied

This will work..

var fruits = ["Banana", "Orange", "Apple", "Mango"];

var a = fruits.toString().indexOf("Apple");

alert(a);

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
May 19, 2017 May 19, 2017

Copy link to clipboard

Copied

Not really. It will give the index in the string, not the index in the array.

Besides,

var fruits = ["orange", "pineapple", "apple", "mango"];

var a = fruits.toString().indexOf("apple");

alert(a);

will also give the wrong index for other reasons! I thought it could be circumvented by adding the quotes themselves, but these disappear in the 'toString' string. Sure, you could add word breaks and use a GREP match, but it still could return the wrong item, depending on the content.

The proposed functions don't have any of these problems.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 19, 2017 May 19, 2017

Copy link to clipboard

Copied

It boils down for me to use .indexOf to find the index of a value in an array, so ill include the code snippet upon use:

  1. var fruits = ["orange", "pineapple", "apple", "mango"]; 
  2. var a = fruits.toString().indexOf("apple"); 
  3. alert(a); 

If you forget to switch the ESTK to InDesign and use "ExtendScript Toolkit CC" it will work fine. I assume the current JavaScript-Libary is used.

Bildschirmfoto 2017-05-19 um 11.47.07.png

But if you execute in InDesign it wont "know" of .indexOf and throw an error:

Bildschirmfoto 2017-05-19 um 11.47.20.png

But if you paste the prototype-function mentioned above, its working with InDesign and ESTK CC.

Bildschirmfoto 2017-05-19 um 11.47.52.png

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 21, 2017 May 21, 2017

Copy link to clipboard

Copied

DBLjan  wrote

It boils down for me to use .indexOf to find the index of a value in an array, so ill include the code snippet upon use:

var fruits = ["orange", "pineapple", "apple", "mango"];   var a = fruits.toString().indexOf("apple");   alert(a);   

If you forget to switch the ESTK to InDesign and use "ExtendScript Toolkit CC" it will work fine.

I assume the current JavaScript-Libary is used.

Bildschirmfoto 2017-05-19 um 11.47.07.png

Hi Jan,

that result is hard to believe. I mean, that the result is actually 2 and not that your snippet is running without error.

Don't know what happened in your case.

Your alert should show 11, because "apple" is already found in "pineapple" and the "a" after "pine" from "pineapple" has index 11 in the string you are building with fruits.toString()  which is: "orange,pineapple,apple,mango".

IndexOfArrayToString-result11.png

Here my result from your code:

scriptAlertShowing11.png

Regards,
Uwe

// EDIT: Added a better looking screenshot.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 21, 2017 May 21, 2017

Copy link to clipboard

Copied

Hm. Ok, you were using two different code snippets.
One with fruits.indexOf() and one with fruits.toString().indexOf().

The alert with result 2 can be explained if you:

1. Used the code with fruits.indexOf()
2. Added the prototype for indexOf()

and ran your code targeting the ESTK.

3. Then removed the prototype code.

4. And ran the snippet again also targeting the ESTK.


Then the prototype for indexOf() is still available in memory and no error is emitted.
Thus the expected result is given: 2 .

That has nothing to do that a more current JavaScript library is suddenly available.

When testing with prototype in the ESTK and targeting the ESTK always do a restart of the ESTK after finishing a test.

Regards,

Uwe

// EDITED.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 21, 2017 May 21, 2017

Copy link to clipboard

Copied

FWIW:

It may be a bit obscure, but Adobe makes the prototype for array.indexOf() available with a special targetengine in InDesign:

#targetengine com.adobe.DesignLibraries.angular_Engine_Id


This targetengine can be found in InDesign CC 2015 and CC 2017 only.

Other methods like array.lastIndexOf() seem to be not provided.

The snippet below is throwing no error and alerts 2 when run with InDesign CC 2015 and CC 2017:

#targetengine com.adobe.DesignLibraries.angular_Engine_Id

var fruits = ["orange", "pineapple", "apple", "mango"];

alert(fruits.indexOf("apple"));

Regards,
Uwe

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 22, 2017 May 22, 2017

Copy link to clipboard

Copied

Thanks Uwe Laubender​ for the insights. Id never have come up with that – to target a secret libary which does actually know the function – the question is: why isnt it kinda unsupported in InD, and what do you guys implement/use to find if and where a value in an array is?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 22, 2017 May 22, 2017

Copy link to clipboard

Copied

Hi Jan,
don't wanted to dig deeper into this, but part of the targetengine's name "coincides" with the name of a folder in InDesign's app package. I do not think it's a real coincident 😉

The folder:

/Applications/Adobe InDesign CC 2017/Resources/CEP/extensions/com.adobe.DesignLibraries.angular

where I think the CC Libraries functionality is accessed.

And indeed here we find:

/jsx/shims.jsx

where the prototype for array.indexOf() is defined.

Together with some other methods like filter() and map().

Regards,
Uwe

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 22, 2017 May 22, 2017

Copy link to clipboard

Copied

You could look up all available targetengine names in the ESTK if you are connected to InDesign.

So com.adobe.DesignLibraries.angular_Engine_Id is not secret at all.

targetengine-com.adobe.DesignLibraries.angular_Engine_Id.png

Regards,
Uwe

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jan 11, 2018 Jan 11, 2018

Copy link to clipboard

Copied

Others have pointed out that array.indexOf might not have been implemented in Illustrator's ExtendScript. If you want to use this function, you will have to provide it. I'd like to share a good resource for these scripts: MDN, Mozilla's Developer Network.

Mozilla's Developer Network provide polyfills for functions that are not implemented in every browser. This is handy, because it allows us to use the newest JS functions even if they don't exist in ExtendScript. And it's easier then subscribing to yet another forum.

The array.indexOf function has a polyfill as well on: Array.prototype.indexOf() - JavaScript | MDN

Remember to include it at the START of your script, or (more neat) to include it at the top:

Let me paste the code for this Polyfill.

if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function indexOf(member, startFrom) {
   /*
  In non-strict mode, if the `this` variable is null or undefined, then it is
  set to the window object. Otherwise, `this` is automatically converted to an
  object. In strict mode, if the `this` variable is null or undefined, a
  `TypeError` is thrown.
  */

   if (this == null) {
   throw new TypeError("Array.prototype.indexOf() - can't convert `" + this + "` to object");
   }

   var
  index = isFinite(startFrom) ? Math.floor(startFrom) : 0,
  that = this instanceof Object ? this : new Object(this),
  length = isFinite(that.length) ? Math.floor(that.length) : 0;

   if (index >= length) {
   return -1;
   }

   if (index < 0) {
  index = Math.max(length + index, 0);
   }

   if (member === undefined) {
   /*
  Since `member` is undefined, keys that don't exist will have the same
  value as `member`, and thus do need to be checked.
  */

   do {
   if (index in that && that[index] === undefined) {
   return index;
   }
   } while (++index < length);
   } else {
   do {
   if (that[index] === member) {
   return index;
   }
   } while (++index < length);
   }

   return -1;
  };
}

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Apr 25, 2022 Apr 25, 2022

Copy link to clipboard

Copied

Adding this class worked for me.

bagonterman_0-1650889144514.png

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines