Arrays of File can't be pushed?

Discussion of Photoshop Scripting, Photoshop Actions and Photoshop Automation in General

Moderators: Tom, Kukurykus

undavide

Arrays of File can't be pushed?

Post by undavide »

Hello,
the following script uses app.openDialog() to do what it says - I've picked a JPG - please look in the comments for the reflect.properties Console output.

Code: Select allvar fileList = app.openDialog ()
var f = fileList[0]
var props = f.reflect.properties;
for (var i = 0; i < props.length; i++) {
    $.writeln("this property " + props.name + " is " + f[props.name]);
}
/* Console output:
this property alias is false
this property created is Fri Mar 08 2013 12:48:23 GMT+0100
this property error is
this property exists is true
this property fsName is /Users/Davide/Desktop/Anita.jpg
this property fullName is ~/Desktop/Anita.jpg
this property absoluteURI is ~/Desktop/Anita.jpg
this property relativeURI is /Users/Davide/Desktop/Anita.jpg
this property modified is Fri Mar 08 2013 12:48:23 GMT+0100
this property name is Anita.jpg
this property displayName is Anita.jpg
this property path is ~/Desktop
this property parent is ~/Desktop
this property type is ????
this property creator is ????
this property hidden is false
this property readonly is false
this property lineFeed is macintosh
this property length is 161078
this property encoding is
this property eof is true
this property __proto__ is [object File]
*/

This other script - which is identical but creates an empty Array first, then uses .push() to add elements in a separate statements gives a completely different Console output - all the File properties are gone.

Code: Select allvar fileList = []
fileList.push(app.openDialog());

var f = fileList[0];
var props = f.reflect.properties;
for (var i = 0; i < props.length; i++) {
    $.writeln("this property " + props.name + " is " + f[props.name]);
}
/* Console output:
this property 0 is ~/Desktop/Anita.jpg
this property length is 1
this property __proto__ is
*/

Apparently, the .push() messes up things - it doesn't seem to be an Array of File objects anymore. Why so?! I'm puzzled.
I've tried to use a tempList, but if you inspect the merged fileList, elements coming from the former have lost all the File properties.

Code: Select allvar fileList = app.openDialog();
var tempList = app.openDialog();
fileList.push(tempList);

var f = fileList[0];
var props = f.reflect.properties;
for (var i = 0; i < props.length; i++) {
    $.writeln("this property " + props.name + " is " + f[props.name]);
}
/* Works for items coming from the fileList
Don't for ones coming from the tempList
*/

Any suggestion?
Thank you!

Davide

UPDATE
It looks like that if you .concat() an Array with itself it works - something that I wouldn't even have tried:
Code: Select allfileList = fileList.concat(app.openDialog ())

Do you think it's worth to signal the .push() thing as a bug?
Mikaeru

Arrays of File can't be pushed?

Post by Mikaeru »

app.openDialog () (without any arguments) always return an array of File objects, even if only one file is selected from the Photoshop Open dialog box. It is different from the function File.openDialog ([prompt, filter, multiSelect]) which cannot select multiple files...

Since app.openDialog () already returns an array in the first place, I don't think it is necessary to push this array into another array...

HTH...
undavide

Arrays of File can't be pushed?

Post by undavide »

Hi Mikaeru,
possibly the example was misleading because as it is, it doesn't appear to be purposeful - I made it just to show the bug.
Though, I don't push arrays of Files into other arrays just for fun

To give you a bit of a framework: I have a Window where the user selects files (which I must keep track of). Since the Select Dialog can be launched multiple times, I have to merge all the selected Files into one unique Array. So the need to concat. Hope this clarifies a bit why I'm unhappy with .push

Best,
Davide
Mikaeru

Arrays of File can't be pushed?

Post by Mikaeru »

undavide wrote:Hi Mikaeru,
To give you a bit of a framework: I have a Window where the user selects files (which I must keep track of). Since the Select Dialog can be launched multiple times, I have to merge all the selected Files into one unique Array. So the need to concat. Hope this clarifies a bit why I'm unhappy with .push :wink:

Apparently, the .push() messes up things - it doesn't seem to be an Array of File objects anymore. Why so?! I'm puzzled.
Because the .push() only pushes the array (of File objects) itself, not its contents/elements/components; if you want to merge all the selected files into a new array, it has to be done either file by file using a loop:
Code: Select allvar fileList1 = app.openDialog();
var fileList2 = app.openDialog();
var mergedFileList = [];
var index;
for (index = 0; index < fileList1.length; index++)
{
    mergedFileList.push (fileList1[index]);
}
for (index = 0; index < fileList2.length; index++)
{
    mergedFileList.push (fileList2[index]);
}

or simply using .concat as you mention:
Code: Select allvar mergedFileList = [];
var fileList1 = app.openDialog();
var fileList2 = app.openDialog();
mergedFileList = mergedFileList.concat (fileList1);
mergedFileList = mergedFileList.concat (fileList2);
// The last two lines of code can also be written:
mergedFileList = mergedFileList.concat (fileList1, fileList2);
// or even shorter:
mergedFileList = fileList1.concat (fileList2);

then you can explore the new merged files array to get the reflect.properties for each file:
Code: Select allfor (index = 0; index < mergedFileList.length; index++)
{
    var f = mergedFileList[index];
    var props = f.reflect.properties;
    for (var i = 0; i < props.length; i++)
    {
        $.writeln("this property " + props.name + " is " + f[props.name]);
    }
}
Mike Hale

Arrays of File can't be pushed?

Post by Mike Hale »

To add to what Mikaeru posted,
It looks like you are trying to combine two arrays. That is done with concat. What you are doing is adding another array to the first array of file objects. So you get [fileObject,fileObject, ... ,Array]
Code: Select allvar a = [1,2];
var b = [3,4];
// push
var p =[1,2,[3,4]];
// concat
var c = [1,2,3,4];

You could could use push, you would just have to change the way you loop thorough the main array. If the element is a fileObject you do whatever, if the element is an array you loop that array.
undavide

Arrays of File can't be pushed?

Post by undavide »

Thanks guys,
I'm happy with .concat now. I was misled by the fact that:

Code: Select allvar fileList = [];
fileList[0] = new File("~/Desktop/1.jpg");
fileList[1] = new File("~/Desktop/2.jpg");
fileList[2] = new File("~/Desktop/3.jpg");

var anotherFileList = [];
anotherFileList[0] = new File("~/Desktop/4.jpg");
anotherFileList[1] = new File("~/Desktop/5.jpg");
anotherFileList[2] = new File("~/Desktop/6.jpg");

fileList.push(anotherFileList);
$.writeln(fileList)
// ~/Desktop/1.jpg,~/Desktop/2.jpg,~/Desktop/3.jpg,~/Desktop/4.jpg,~/Desktop/5.jpg,~/Desktop/6.jpg

Which made me think that fileList.length was 6 - and not 4 as it actually is!
Problem solved now, thanks!

Davide
Mikaeru

Arrays of File can't be pushed?

Post by Mikaeru »

undavide wrote:I was misled by the fact that:
Code: Select all[...]
$.writeln(fileList)
// ~/Desktop/1.jpg,~/Desktop/2.jpg,~/Desktop/3.jpg,~/Desktop/4.jpg,~/Desktop/5.jpg,~/Desktop/6.jpgWhich made me think that fileList.length was 6 - and not 4 as it actually is!

Yes, I remember having been mistaken the same way in a very similar situation.
That's why I usually always add .toSource() to the complex data I want to display for debugging, using either alert() or $.writeln():
Code: Select all$.writeln(fileList.toSource());
// [new File ("~/Desktop/1.jpg"), new File ("~/Desktop/2.jpg"), new File ("~/Desktop/3.jpg"), [new File ("~/Desktop/4.jpg"), new File ("~/Desktop/5.jpg"), new File ("~/Desktop/6.jpg")]]Definitely more verbose, but quite accurate...
undavide

Arrays of File can't be pushed?

Post by undavide »

Mikaeru wrote:That's why I usually always add .toSource() to the complex data I want to display for debugging, using either alert() or $.writeln():


Neat!! I didn't know that - I've been using toSource() just a couple of times for bridgeTalk, definitely useful here; thanks for the tip!

Davide
Mike Hale

Arrays of File can't be pushed?

Post by Mike Hale »

Another tip you may need if your scripts need to run in older versions of Photoshop. Xbytor has a comment in stdlib that says concat can fail. I have not run into that problem myself but I don't normally write scripts that need to support all( or most ) versions. But I think it must have been in a early version( Photoshop 7, CS, or CS2 )