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

Getting the parent element with JSFL

Participant ,
Nov 29, 2017 Nov 29, 2017

Copy link to clipboard

Copied

This seems like the simplest thing in the world, but I can't figure out a simple way how, if I'm currently in a symbol, to get access to the element that IS the current symbol I have open, on the timeline of the symbol that the current symbol is in.

The way I've done it until now is really clunky. There has to be a better way. Currently, I use document.exitEditMode() to exit into the parent timeline, and use document.selection[0] to access the currently selected element. Is there a way to do this without exiting the symbol?

Views

3.3K

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

Community Expert , Dec 07, 2017 Dec 07, 2017

Wow! This is nice!

I never thought I could get only the keyframes.

It will certainly lower the number of iterations. I did a small modification based on what you've done.

Instead of just j++ I've modified to j += timeline.layers.frames.startFrame + timeline.layers.frames.duration.

Please let me know if it can be even better.

function getParent(docArray)

{

    for (var i = 0; i < docArray.length; i++)

    {

        if (docArray.libraryItem.timeline == fl.getDocumentDOM().getTimeline() && docArray.selected

...

Votes

Translate

Translate
Community Expert ,
Nov 29, 2017 Nov 29, 2017

Copy link to clipboard

Copied

how did you get to symbol editing?  via the library symbol (and you want the library name) or via a timeline instance and you want the instance name?  or something else?

Votes

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
Participant ,
Nov 30, 2017 Nov 30, 2017

Copy link to clipboard

Copied

I'm talking about if you dive into nested symbols from the timeline rather than opening them through the library. I want to get the instance that I dove into to open the currently open symbol. not just the name, but the actual object.

Votes

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 ,
Nov 30, 2017 Nov 30, 2017

Copy link to clipboard

Copied

i don't understand your work-flow.

you have a fla that you want to manipulate using jsfl, correct?

you create a jsfl file and you run it from a fla (commands>run>..), correct?

Votes

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
Participant ,
Nov 30, 2017 Nov 30, 2017

Copy link to clipboard

Copied

I have a symbol sitting on my timeline here.

Untitled-1.png

I dive into it manually by double clicking to edit in place. You can see it reads Scene 1>Symbol 1 on the top left here.

Untitled-2.png

I then want to be able to run a .jsfl script that will give me access to the instance selected in the FIRST image. Is there a way to do that without using document.exitEditMode() and accessing the currently selected object with document.selection[0]? It's not relevant, but I run my JSFLs from a custom toolbar I created.

Votes

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 ,
Nov 30, 2017 Nov 30, 2017

Copy link to clipboard

Copied

Depending on the type of element you have selected, it may have a .parent property that you can read.

Votes

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
Participant ,
Nov 30, 2017 Nov 30, 2017

Copy link to clipboard

Copied

fl.trace(fl.getDocumentDOM().getTimeline().parent);

Gives me "undefined".

Votes

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 ,
Nov 30, 2017 Nov 30, 2017

Copy link to clipboard

Copied

Ah, a timeline object. Does this provide what you need?

Adobe Flash Professional * timeline.name

If not, well... using two or three lines of code to get a reference is about the least clunky thing I've ever had to do in JSFL. It is not an elegant API. If you can get it to do what you want at all, consider yourself lucky.

Votes

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 ,
Dec 01, 2017 Dec 01, 2017

Copy link to clipboard

Copied

Hi,

Well, at least for me it's not a trivial thing... I've tested a lot of solutions but none has worked. The exitEditMode seems to be the only obvious way.

function getParent()

{

    var doc = fl.getDocumentDOM();

    var current;

   

    doc.exitEditMode();

    current = doc.selection[0];

   

    if (!current)

        return;

   

    doc.enterEditMode('inPlace');

   

    fl.trace("current: " + current + ", current.name: " + current.name);

}

getParent();

The process is unnoticeable for the user. So I think it's a valid solution.

And Adobe should insert a parent property. It will certainly make your lives easier.

Regards,

JC

Votes

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
Participant ,
Dec 06, 2017 Dec 06, 2017

Copy link to clipboard

Copied

I think I see what you're after.

You want to be able to "dive into" a symbol on the stage, accessing its timeline, do a certain thing, then, affect the instance in the timeline you originally accessed it through.

The sad thing about JSFL is that all of the information it can access is new each time you initiate the script.

So, I suggest altering your workflow slightly.

Use a command to "dive into" selected items rather than double-clicking.

I've found tremendous improvement in workflow by making a command to do this. (When I'm hot-keying my way through a scene, double-clicking a precise location on the stage is a real nuisance). Secondly, by using a command, you can add extra functionality (which is what you need).

As you dive into your symbol to edit it, you can also have the command record your starting location (the parent timeline, the frame number, etc) into a temporary text file in the location of your choosing. I'd use the config directory since it's already defined as a property of the fl object. Adobe Flash Professional * fl.configURI

Record the symbol object's information, the frame you're on, etc.

Once you write that text file, you've essentially left a bookmark for yourself.

When you're inside the embedded symbol, you can then run a second script which will get the "bookmarked" timeline information you recorded to that text file. Then, you can do whatever you want.

Votes

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
Participant ,
Dec 06, 2017 Dec 06, 2017

Copy link to clipboard

Copied

no, I don't need to run any script twice, or more than one script. diving into the symbol is done manually. at no point do I need the script to dive into any symbol. Using JSFL, I want to be able to get access to the instance object I manually dived into on the parent timeline.

also, the timeline object only gives me access to the currently open timeline. I need the timeline of the timeline that the symbol instance is sitting on. it looks like the only way to do that is the clunky method I mentioned.

Votes

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
Participant ,
Dec 07, 2017 Dec 07, 2017

Copy link to clipboard

Copied

Oh, that's much easier! I thought you wanted to edit the timeline of the "host" or "parent" timeline.

You just need to know the name of the symbol in the library that you want to access.

So, if your keyframe has one element, element[0], and that element is the symbol you're interested in editing, find its library item and that library item's name:

element[0].libraryItem.name

Having that information, I made a function a while back to give me access to the timeline object of that element.

First, define some basic variables:

var curr_doc = fl.getDocumentDOM().library;

var curr_lib = curr_doc.library;

Then, this function returns the timeline object:

function getTL(TimelineName){

var the_tl = Items[curr_lib.findItemIndex(TimelineName)].timeline;

return the_tl;

}

So, you'd run:

mySymbolTimeline = getTL(theSymbolLibraryName);

And, then,  "mySymbolTimeline" will have all the same properties you'd use to work with "current timeline."

Votes

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
Participant ,
Dec 07, 2017 Dec 07, 2017

Copy link to clipboard

Copied

I don't think you're quite understanding what I'm asking. I want the element (i.e. tline.layers[0].frames[0].elements[0]) that I double clicked to edit in place the symbol that I currently have open. That means I need access to the timeline ABOVE the one that's currently open. When I run the script, I wouldn't know what that timeline is, since I only have the nested timeline open right now. It's also possible that multiple instances of this opened symbol exist on that parent timeline. even on the same frame. all with different properties (position, rotation, etc), so getting access to the right one is important.

Votes

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 ,
Dec 07, 2017 Dec 07, 2017

Copy link to clipboard

Copied

I think I've finally found the solution for this.

Basically I created a function to get ALL symbols of the entire document, no matter how nested or on what frame they are. This function returns a array with all these elements.

Then I call a function to check if the elements of this array has a timeline that is equal to the current symbol's timeline AND if the current element is selected. This is because all elements in edit mode has to have their parent selected.

Please run various tests and tell me if this works and if there is some problem.

Please notice that some actions will only get updated when you exit de edit mode. For example, if you rotate the parent symbol, you will only see it when you exit the edit mode.

function getParent(docArray)

{

    for (var i = 0; i < docArray.length; i++)

    {

        if (docArray.libraryItem.timeline == fl.getDocumentDOM().getTimeline() && docArray.selected)

            return docArray;

    }

   

    return fl.getDocumentDOM().timelines[0];

}

function getAll(timeline)

{

    var array = [];

   

    getAll2(timeline);

   

    function getAll2(timeline)

    {

        for (var i = 0; i < timeline.layers.length; i++)

        {           

            for (var j = 0; j < timeline.layers.frames.length; j++)

            {

                for (var k = 0; k < timeline.layers.frames.elements.length; k++)

                {

                    var element = timeline.layers.frames.elements;

                   

                    if (element.instanceType == "symbol")

                    {

                        array.push(element);

                        getAll2(element.libraryItem.timeline);

                    }                   

                    else

                        continue;

                }           

            }

        }   

    }

   

    return array;

}

fl.trace(getParent(getAll(fl.getDocumentDOM().timelines[0])));

fl.trace(getParent(getAll(fl.getDocumentDOM().timelines[0])).name);

Regards,

JC

Votes

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
Participant ,
Dec 07, 2017 Dec 07, 2017

Copy link to clipboard

Copied

@JoãoCésar:

Just curious...won't this script grab the elements on EVERY frame in a timeline, not just keyframes?

So, I think you'd get sub-arrays with a number of items equal to the frame length of the timeline.
Right?

If that's the case, you could add something like this (see below) to get the elements from just the keyframes:

function getLayerKeys(thisLayer){ //input: a layer object, output: returns array of frame indexes containing keyframes.

var tot_fr = thisLayer.frameCount;

var i=0;

var stFrame;

var durr;

var keyFrIdx = [];

var outArray = [];

while(i<tot_fr){

keyFrIdx.push(i);

stFrame = thisLayer.frames.startFrame;

durr = thisLayer.frames.duration;

i = stFrame + durr;

}

outArray = keyFrIdx;

return outArray;

}

Votes

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 ,
Dec 07, 2017 Dec 07, 2017

Copy link to clipboard

Copied

Wow! This is nice!

I never thought I could get only the keyframes.

It will certainly lower the number of iterations. I did a small modification based on what you've done.

Instead of just j++ I've modified to j += timeline.layers.frames.startFrame + timeline.layers.frames.duration.

Please let me know if it can be even better.

function getParent(docArray)

{

    for (var i = 0; i < docArray.length; i++)

    {

        if (docArray.libraryItem.timeline == fl.getDocumentDOM().getTimeline() && docArray.selected)

            return docArray;

    }

   

    return fl.getDocumentDOM().timelines[0];

}

function getAll(timeline)

{

    var array = [];

    var count = 0;

   

    getAll2(timeline);

   

    function getAll2(timeline)

    {

        for (var i = 0; i < timeline.layers.length; i++)

        {           

            for (var j = 0; j < timeline.layers.frames.length; j += timeline.layers.frames.startFrame + timeline.layers.frames.duration)

            {

                for (var k = 0; k < timeline.layers.frames.elements.length; k++)

                {

                    var element = timeline.layers.frames.elements;

                    count++;                   

                   

                    if (element.instanceType == "symbol")

                    {

                        array.push(element);

                        getAll2(element.libraryItem.timeline);

                    }                   

                    else

                        continue;

                }           

            }

        }   

    }

   

    return array;

}

fl.trace(getParent(getAll(fl.getDocumentDOM().timelines[0])));

fl.trace(getParent(getAll(fl.getDocumentDOM().timelines[0])).name);

Regards,

JC

Votes

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
Participant ,
Dec 07, 2017 Dec 07, 2017

Copy link to clipboard

Copied

bluebeezle​...
Just curious if we're getting close to what you're after.

So far, I'm not entirely sure I'm clear on what you'd like to do to the symbol instance in the parent timeline.

And, then, if there are multiple instances, I don't know how to be certain that you're editing the correct one.
Or, if you want to do this to all of them.

At a guess, is this something to do with the element transformations?

Votes

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
Participant ,
Dec 09, 2017 Dec 09, 2017

Copy link to clipboard

Copied

LATEST

yup, that works! I was really thinking something so basic would be more built in, but this works great. thanks!

@chrisgelles so, my need for this has come up a couple times. The most recent one is a way of getting the globalized transform matrix of the currently open symbol, yes. The other is that I have a script that exports from within the currently open symbol, but it needs to make changes to the file for each export. So I copy the file multiple times before performing the function on each of them. That means I have to dive back into the symbol that was open in the original file (or at least have access to its timeline) in each of the copies of the file. So I need to find the path from the main timeline down to the nested symbol by recording the list of indices for frame and element numbers.

As I mentioned before, I'd found a workaround with the exitEditMode feature in the meantime, but I figured something so basic would have had a proprietary solution that I was just missing.

Votes

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