Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

.indexOf is not a function :(

Advocate ,
May 18, 2017 May 18, 2017

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
28.5K
Translate
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

Community Expert , 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

...
Translate
People's Champ ,
May 18, 2017 May 18, 2017

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;

  }

}

Translate
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 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 right: it's properly called "ExtendScript".

Translate
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
People's Champ ,
May 18, 2017 May 18, 2017

My bad indeed

Translate
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

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!

Translate
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
Advisor ,
Jul 20, 2022 Jul 20, 2022

@DBLjan 

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

Translate
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 Beginner ,
Oct 01, 2023 Oct 01, 2023
LATEST

Yes! Thank you @DBLjan for the snippet; this also worked for Illustrator code.

Translate
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

Just include prototype definitions:

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

JavaScriptClassEnhancements for JavaScript Array Class

Translate
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

This will work..

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

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

alert(a);

Translate
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 19, 2017 May 19, 2017

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.

Translate
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

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

Translate
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

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.

Translate
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

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.

Translate
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

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

Translate
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

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?

Translate
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

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

Translate
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

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

Translate
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

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; };}

Translate
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

Adding this class worked for me.

bagonterman_0-1650889144514.pngexpand image

 

Translate
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