GreenSock AS vs JS

116 views
Skip to first unread message

Steven Stark

unread,
May 10, 2013, 5:46:49 PM5/10/13
to jangaro...@googlegroups.com
Hello,

I have followed this thread and created my own custom Greensock JS artifact:


I have the AS3 classes, and I ( assume ) the js is copying over correctly... now I am modifying the project to work with the new code, still working my way through the errors trying to compile the project.

As I work away I have had a few questions in the back of my head.

First off, this project was made using the AS3 version of greensock, full of loaders and easing references.

In the JS version there are no loaders and eases use strings, not class references.

Also, I am not entirely clear about how to go about 'stubbing' the JS functions in my new AS3 Classes. For example, TweenLite.

in as3 it's com.greensock.TweenLite

in js it's just TweenLite

I want my project to use the JS version, but see as com.greensock.TweenLite, so I made that as3 class that looks like: 

package com.greensock {

public native function get TweenLite():TweenLite;

}


This is taken from the soundManager2 example, however I am not familiar with the native scope and am not clear what's actually going on here. 


Now what about easing?

I did the same for com.greensock.easing.Linear, but really I would want this to return a string because there is no class associated with this in JS.


thanks for any insight on this,

-Steven

Steven Stark

unread,
May 10, 2013, 5:49:18 PM5/10/13
to jangaro...@googlegroups.com
When I said "I have the AS3 classes", I meant "I have the 'fake' AS3 classes"

Steven Stark

unread,
May 10, 2013, 7:55:25 PM5/10/13
to jangaro...@googlegroups.com
for example, I would like to add this to the TweenLite js class.

public function delayedCall( delay, callback ){
        setTimeout(delay, callback );
    }


It'd be cleaner to add this to the .as files instead of having to modify the greensock js source.

Frank

unread,
May 13, 2013, 5:09:46 AM5/13/13
to Jangaroo Users
On May 10, 11:46 pm, Steven Stark <sstark.st...@stevenstark.com>
wrote:
> Hello,
>
> I have followed this thread and created my own custom Greensock JS artifact:
>
> https://groups.google.com/forum/?fromgroups=#!topic/jangaroo-users/Sq...

Cool! Thanks for the engagement!

> I have the AS3 classes, and I ( assume ) the js is copying over
> correctly... now I am modifying the project to work with the new code,
> still working my way through the errors trying to compile the project.
>
> As I work away I have had a few questions in the back of my head.
>
> First off, this project was made using the AS3 version of greensock, full
> of loaders and easing references.
>
> In the JS version there are no loaders and eases use strings, not class
> references.

Well, then to be compatible with the Greensock JS implementation, you
would have to change your AS client code. The other option is to use
the original Greensock AS API and build an adapter to the JS
implementation, which of course creates a bit overhead, but simplifies
porting AS code and keeping a single code base if you want to do Flash
and HTML5 a lot.

> Also, I am not entirely clear about how to go about 'stubbing' the JS
> functions in my new AS3 Classes. For example, TweenLite.
>
> in as3 it's com.greensock.TweenLite
>
> in js it's just TweenLite
>
> I want my project to use the JS version, but see as
> com.greensock.TweenLite, so I made that as3 class that looks like:
>
> package com.greensock {
>
> public native function get TweenLite():TweenLite;
>
> }
>
> This is taken from the soundManager2 example, however I am not familiar
> with the native scope and am not clear what's actually going on here.
>
> Now what about easing?
>
> I did the same for com.greensock.easing.Linear, but really I would want
> this to return a string because there is no class associated with this in
> JS.
>
> thanks for any insight on this,
>
> -Steven

The native scope just allows to define a function/method without
specifying its implementation. As the implementation is already there
(in JS), this is exactly what we want to do in the AS API.
Additionally, in Jangaroo, there is an annotation [Native] which tells
the compiler to not generate any code from this AS source file.

Now it is essential whether TweenLite is a class (in JavaScript: a
constructor function) or just a global object ("singleton").
Your code won't work, because you use "TweenLite" as a global object
*and* as its type...

If TweenLite is a class, you'd write

package com.greensock {

[Native]
public class TweenLite {
// put TweenLite's fields and methods here, using the "native"
keyword!
}
}

If it is a global object or function (that is not used with "new", but
simply called), you can denote it as an AS global object or function
inside a package:

package com.greensock {

[Native]
public const TweenLite:Object;

}

If you want to give such a global object a more specific type, you'd
have to declare that in a separate AS source file. It can be a purely
made up interface, since it is just there to provide typed access to
the fields and methods of the global JS object. As a best practice, I
use the name of the global object prefixed with "I" for such an
interface:

package com.greensock {

[Native]
public const TweenLite:ITweenLite;

}


and in com/greensock/ITweenLite.as:

package com.greensock {

public interface ITweenLite {
// put fields (as function get/set) and methods here!
}

}

Now the last thing you need is to create an alias from
com.greensock.TweenLite to (top-level) TweenLite. Jangaroo 3 will
provide support for such aliases through a parameter of the [Native]
annotation, but for Jangaroo 1 or 2, you have to create the alias as a
JavaScript object. After greesock.js and the Jangaroo Runtime are
loaded, you can use the utility function joo.getOrCreatePackage() to
create the alias:

joo.getOrCreatePackage("com.greensock").TweenLite = TweenLite;


Hope that helps,

-Frank-

Steven Stark

unread,
May 13, 2013, 7:55:30 PM5/13/13
to jangaro...@googlegroups.com
Thank you very much for this, that is exactly what I needed to know. makes perfect sense. :)



On Friday, May 10, 2013 2:46:49 PM UTC-7, Steven Stark wrote:

Steven Stark

unread,
May 13, 2013, 9:03:16 PM5/13/13
to jangaro...@googlegroups.com
Hit a wall with this approach on compiling.

TweenLite.as(4): Error: in column 9: constant must be initialized

so I try it with = {}, which feels wrong but I try anyhow, and I get null pointer error curing the compile. Is this something obvious? If not I might just move on to my next idea, and trash this one.. it may be conceptually flawed.


[INFO] --- jangaroo-maven-plugin:0.8.1:compile (default-compile) @ joo-greensock ---
[info] Compiling 12 joo source files to G:\WEBSITE_FILES\jangaroo\jangaroo-framework-3\joo-greensock\target\classes\joo\classes
java.lang.NullPointerException
at net.jangaroo.jooc.FieldDeclaration.analyze(FieldDeclaration.java:81)
at net.jangaroo.jooc.CompilationUnit.analyze(CompilationUnit.java:149)
at net.jangaroo.jooc.Jooc.run1(Jooc.java:139)
at net.jangaroo.jooc.Jooc.run(Jooc.java:100)
at net.jangaroo.jooc.mvnplugin.AbstractCompilerMojo.compile(AbstractCompilerMojo.java:314)
at net.jangaroo.jooc.mvnplugin.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:200)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)



I do have another question though. ( the next idea I mentioned above )

I like the idea of writing the adapter that you mentioned, right now I am less worried about greensock overhead than I am about one code base for as3 and js compilation. That said, I do very much want to use the js version of greensock.

so let's say I just want to call the js TweenLite function from within my own TweenLite class, can I just call it as if I was in HTML, does that work? Or, maybe referencing window.TweenLite or window['TweenLite']?

thanks again,

-Steven





On Friday, May 10, 2013 2:46:49 PM UTC-7, Steven Stark wrote:

Kleine, Moritz

unread,
May 14, 2013, 2:27:19 AM5/14/13
to jangaro...@googlegroups.com

Hi Steven, how does TweenLite look like? If you had declared your constant ‘native’ you wouldn’t get that error and you should definitely not initialize it with {}. Think of native as “this is defined in the JS lib”. Then you’d initialize the native constant with

 

joo.getOrCreatePackage("com.greensock").TweenLite = TweenLite;

 

(as Frank mentioned earlier) in some bootstrap code where TweenLite is a known variable. You can as well use window.TweenLite or window['TweenLite'] instead. In your AS code you’d always access that singleton variable you’ve set up initially (com.greensock.TweenLite).

Cheers, Moritz

--
You received this message because you are subscribed to the Google Groups "Jangaroo Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jangaroo-user...@googlegroups.com.
To post to this group, send email to jangaro...@googlegroups.com.
Visit this group at http://groups.google.com/group/jangaroo-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Steven Stark

unread,
May 15, 2013, 2:28:48 PM5/15/13
to jangaro...@googlegroups.com
Thanks to the help here, I have made some good progress with this approach. I am liking this a lot.

One limitation I am facing is static methods.

First, my setup:

the web app has with it all the greensock js libs, and in js they resolve as both TweenLite and com.greensock.TweenLite

I have then setup the module as suggested by Frank, with the interface and the getOrCreatePackage

in my main application.as I have a working test:

new TweenLite( box, 5, { alpha:0, x: 300, y: 300, rotation: 180 } )

and the box is animating as I expect ( I am using canvas )

if, however, I try and use the static function .to, the compiler errors out.

I can not define a static function in an interface, that goes against the design of interfaces. 

but if I code like this it works:

TweenLite['to']( box, 5, { alpha:0, x: 300, y: 300, rotation: 180 } )

yes this would work on as3 as well, so it is a workable solution, however it's kinda ugly. Is there a work around for this so that I can compile with .to instead of ['to'] ?

Steven Stark

unread,
May 15, 2013, 2:48:22 PM5/15/13
to jangaro...@googlegroups.com
Ok I figured out how to get .to working with the compiler. This is my TweenLite class:

package com.greensock {
import flash.display.DisplayObject;

public class TweenLite{

        [Native]
        public const TweenLite:ITweenLite;

        [Native]
        public static function to( target:DisplayObject, duration:Number, data:Object ){};
    }





... but then these variations also work just fine:


package com.greensock {
import flash.display.DisplayObject;

[Native]
public class TweenLite{

        [Native]
        public static function to( target:DisplayObject, duration:Number, data:Object ){};
    }




and


package com.greensock {
import flash.display.DisplayObject;

public class TweenLite{

        public static function to( target:DisplayObject, duration:Number, data:Object ){};
    }





So I guess my question is which style is the proper one? Is [Native] actually doing anything useful?

Steven Stark

unread,
May 15, 2013, 4:40:42 PM5/15/13
to jangaro...@googlegroups.com
I hope I'm not annoying anyone with my posts. ;)

I have another configuration that works, and is much closer to what Frank suggested:

TweenLite.as:

package com.greensock {

    [Native]
    public const TweenLite:ITweenLite;


ITweenLite.as:

package com.greensock {
import flash.display.DisplayObject;

public interface ITweenLite {

        [Native]
        function to( target:DisplayObject, duration:Number, data:Object );
}



Steven Stark

unread,
May 15, 2013, 5:44:42 PM5/15/13
to jangaro...@googlegroups.com
Ok I have interfaced all the functions for TweenLite, TimelineLite and the eases. This code is working! :D:D


            TweenLite.delayedCall( 2, function(){
                var timeline = new TimelineLite();
                timeline.append(
                    TweenLite.to( box, 5, { alpha:0, x: 300, y: 300, rotation: 180, ease: Elastic.easeOut } )
                );
                timeline.append(
                    TweenLite.to( box, 5, { alpha:1, x: 1, y: 1, rotation: 0, ease: Bounce.easeOut } )
                );
                timeline.append(
                    TweenLite.to( box, 5, { alpha:0, x: 500, y: 400, rotation: 3600, ease: Linear.easeOut } )
                );
            });



the only thing not working is that the compiler is making IntelliJ complain about instantiation ( new TimelineLite ), is 'method expression is not of Function type' because we declared it as static... which it is, also, but it can be instantiated as well.

but the good news is that it still does actually compile just fine, even with this big red error visible in IntelliJ, but that's something I don't mind ignoring and continuing on.

Steven Stark

unread,
May 15, 2013, 5:48:12 PM5/15/13
to jangaro...@googlegroups.com
One other thing to note.

Running this code does not quite produce code as expected.

if I turn off cacheAsBitmap, which renders as a div, the animation is wild and flies off the left of the screen.

with cacheAsBitmap on, which renders in it's own canvas, the animation is very close to flash, however it seems to move first to x 300, then to y 300, instead of moving in both directions at the same time. Also easing the alpha with a bounce causes errors where the box pops between 100% alpha and 0% alpha due the overshoot of the bounce ease.

Steven Stark

unread,
May 16, 2013, 9:48:20 PM5/16/13
to jangaro...@googlegroups.com
So the end result of this is really cool. Thanks again for the help! I am going to see if I can share the code with the community here, but it's up to my work to let me.

Anyhow, I also included all the greensock loaders into this, and that was as simple as adding the .as classes needed for the loaders, and nothing else. Jangaroo took care of the rest for me. :)

core js tweens with compiles js loaders, resulting in more js greensock code than what's available online. Couldn't ask for more.


Frank

unread,
May 17, 2013, 3:10:46 AM5/17/13
to jangaro...@googlegroups.com
That's really awesome!
So is there any remaining open question in this thread that I missed?
-Frank-

Steven Stark

unread,
May 17, 2013, 11:56:08 AM5/17/13
to jangaro...@googlegroups.com
the only remaining question is about the compiler error in the IDE. I still do get that, but I just ignore it. Maven doesn't complain at all.

-Steven

Steven Stark

unread,
May 17, 2013, 1:53:12 PM5/17/13
to jangaro...@googlegroups.com
for a little more information, and a re-cap, it works:

when I compile or install and main project's pom file.

it fails when I compile or install the test-app pom file on it's own, which has the usage code in it.

it is successful when just compiling greensock on it's own.


The issue is how greensock is used, as both a const function and as an instantiated class.

This is my setup:

package com.greensock {

        [Native]
        public const TweenLite:ITweenLite;



... and, of course, if I set this up as a class, then I have the opposite problem that the static functions aren't found.

In both cases I can get output to compile, it's only the IDE and the webapp pom's that are complaining, but I can ignore this and continue by using the root project pom.



Steven Stark

unread,
May 17, 2013, 3:29:13 PM5/17/13
to jangaro...@googlegroups.com
one more question related to this:

why should we use joo.loadScript instead on a script tag?

when I use joo.loadScript it deleted the body node of the html page, I am left with only  the html and head elements. This doesn't happen on every project, only my newest one and only today, so this must be an edge case. My solution was to use script tags instead.

my usage:

joo.loadScript( parentDir + CLASSES[ c ]+".js", parentDir + CLASSES[ c ]+".min.js" );


note: yes, both unminified and minified are at the requested locationsnote

Frank

unread,
May 20, 2013, 9:52:38 AM5/20/13
to jangaro...@googlegroups.com
Hi Steven,

to answer that question first, joo.loadScript() uses document.write() to create a script tag, so it must only be used in scripts that are rendered with the page, not scripts that are loaded asynchronously, or document.write() will overwrite the current document!
The idea is that you develop Jangaroo *modules* that consist of JS code generated from ActionScript through the Jangaroo compiler *plus* some "native" JavaScript. The Maven build process takes care of including a JavaScript file of each module, which must be named joo/<artifactId>.module.js, where <artifactId> is the artifactId (sic!) of that module. This JS fragement should use joo.loadScript() to load all needed JavaScript libraries. The advantage is that the web page loading the Jangaroo application does not need to know about needed JavaScript libraries, but instead just loads joo/jangaroo-application.js, which is generated by the war-package goal used in the "war"-packaged Jangaroo application.
A detailed reference of the (Jangaroo 1) Maven build process can be found here:
https://github.com/CoreMedia/jangaroo-tools/wiki/Maven-Build-Process

Greetings
-Frank-

Frank

unread,
May 20, 2013, 9:56:12 AM5/20/13
to jangaro...@googlegroups.com
P.S.: joo.loadScript() also supports loading a different script in "debug" mode.
Debug mode is switched on by adding #joo.debug to the page URL.
(See also: http://www.jangaroo.net/tutorial/debugging/)
If debug mode is on *and* joo.loadScript() provides a second parameter, that second script is loaded instead of the first one.
A typical example looks like this:
joo.loadScript("ext-js/ext-all.js", "ext-js/ext-all-debug.js");

Frank

unread,
May 20, 2013, 10:06:07 AM5/20/13
to jangaro...@googlegroups.com
On Friday, May 17, 2013 7:53:12 PM UTC+2, Steven Stark wrote:
The issue is how greensock is used, as both a const function and as an instantiated class.

This is my setup:

package com.greensock {

        [Native]
        public const TweenLite:ITweenLite;



... and, of course, if I set this up as a class, then I have the opposite problem that the static functions aren't found.

In both cases I can get output to compile, it's only the IDE and the webapp pom's that are complaining, but I can ignore this and continue by using the root project pom.

 
I think the problem is how you define the JavaScript API in ActionScript.
The approach with const plus interface should only be used for singletons. Since JavaScript is an object-based, not class-based language, singleton objects are quite common.
However, if the JavaScript library simulates classes with static and non-static members, this can only be expressed in ActionScript through classes, not through interfaces. You annotate the class as [Native] and declare each and every method, be it static or non-static, using the "native" keyword:

package com.greensock {

[Native]
public class TweenLite {

  public static native function getSomeStaticProperty():String;

  // constructor cannot be "native", but the implementation does not matter!
  public function TweenLite() {
  }

  public native function someMethod(foo:String):int;

  // ....
}
}

The "native" keyword is only used so you don't have to write down a meaningless method body. In any case, a [Native] class does not produce any JavaScript code, but relies on the corresponding JavaScript objects to be present at runtime. The ActionScript class is just used as a reference for the compiler and the IDE.
Reply all
Reply to author
Forward
0 new messages