You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@flex.apache.org by OmPrakash Muppirala <bi...@gmail.com> on 2016/01/07 02:58:06 UTC

[FlexJS] Extending builtin HTML elements

Is this supposed to work?

MyButton.as
package {
public class MyButton extends HTMLButtonElement {
public function MyButton() {
super();
this.addEventListener("click", button_clickListener, false);
}
private function button_clickListener(event : MouseEvent) : void {
alert("Hello World");
}
}
}

WebProject1.as
package {
public class WebProject1 {
public function WebProject1() {
var button : MyButton = document.createElement("button") as MyButton;
button.innerHTML = "Press Me";
document.body.appendChild(button);
}
}
}

This code compiles fine, but when I run it, I am getting a null for
variable button.
Console log:
Uncaught TypeError: Cannot set property 'innerHTML' of null

Thanks,
Om

Re: [FlexJS] Extending builtin HTML elements

Posted by OmPrakash Muppirala <bi...@gmail.com>.
On Wed, Jan 6, 2016 at 6:35 PM, Andy Dufilie <an...@gmail.com> wrote:

> button is null because document.createElement("button") is not an instance
> of MyButton.
>

Ah, okay.  Seems obvious now.

Thanks,
Om


> Is this supposed to work?
>
> MyButton.as
> package {
> public class MyButton extends HTMLButtonElement {
> public function MyButton() {
> super();
> this.addEventListener("click", button_clickListener, false);
> }
> private function button_clickListener(event : MouseEvent) : void {
> alert("Hello World");
> }
> }
> }
>
> WebProject1.as
> package {
> public class WebProject1 {
> public function WebProject1() {
> var button : MyButton = document.createElement("button") as MyButton;
> button.innerHTML = "Press Me";
> document.body.appendChild(button);
> }
> }
> }
>
> This code compiles fine, but when I run it, I am getting a null for
> variable button.
> Console log:
> Uncaught TypeError: Cannot set property 'innerHTML' of null
>
> Thanks,
> Om
>

Re: [FlexJS] Extending builtin HTML elements

Posted by Alex Harui <ah...@adobe.com>.

On 1/7/16, 1:55 AM, "omuppi1@gmail.com on behalf of OmPrakash Muppirala"
<omuppi1@gmail.com on behalf of bigosmallm@gmail.com> wrote:

>> >I'm wondering if document.createElementNS might be useful here?
>>
>> Well, I doubt it.  IMO, you are trying to mix scripting APIs with
>> object-oriented APIs.  Just like you wouldn't create a plain button by
>> calling "new HTMLButtonElement()", you have to pick a pattern and stick
>> with it.
>>
>> The FlexJS framework components internally call createElement for you
>>and
>> wrap the HTMLButtonElement since you can't actually subclass it and
>> instantiate it.  If HTML had an extensible component/element API we
>> probably wouldn't have bothered to create FlexJS.
>>
>> Then you can use all object-oriented APIs/patterns since that's what
>>we're
>> used to in ActionScript/Flash.  I suppose you could create another
>> component set that even more thinly wraps HTMLButtonElement than we do
>> already, and then make "new HTMLButtonElement()" work.  I've chosen to
>> pack a bit more in org.apache.flex.html.Button so it can have more
>> Flex-like APIs
>>
>> -Alex
>>
>
>
>Turns out that WebComponents provides exactly these kinds of APIs.  And
>they seem to be working (almost) fine with FlexJS/Falcon :-)
>
>Here is how I am making this work:
>
>MyButton.as
>
>package {
>public class MyButton extends HTMLButtonElement {
>public function MyButton(label) {
>super();
>}
>public function createdCallback() {
>    var sr = this['createShadowRoot'](); //TODO:FIXME
>HTMLElement.createShadowRoot is typed to be an Object instead of a
>Function
>sr.innerHTML = 'Click Meeee';
>}
>}
>}
>
>WebProject1.as
>
>package {
>
>public class WebProject1 {
>public function WebProject1() {
>var MyButtonClass = document['registerElement']('my-button', {
>//TODO:FIXME
>HTMLElement.registerElement is typed to be an Object instead of a Function
> prototype: Object['create'](MyButton['prototype']), //TODO:FIXME
>Object.create and Object.prototype is missing
> 'extends': 'button'});

Are you working with the nightly of Falcon?  Object.create should be there.

>
>I don't know how useful all this is, but is very cool that we can support
>WebComponents out of the box.
>
>I am going to experiment more with this!

Yes, certainly interesting and good to know.

-Alex


Re: [FlexJS] Extending builtin HTML elements

Posted by OmPrakash Muppirala <bi...@gmail.com>.
On Wed, Jan 6, 2016 at 11:57 PM, Alex Harui <ah...@adobe.com> wrote:

>
>
> On 1/6/16, 11:36 PM, "omuppi1@gmail.com on behalf of OmPrakash Muppirala"
> <omuppi1@gmail.com on behalf of bigosmallm@gmail.com> wrote:
>
> >>
> >> Add the following as the ASDoc for the WebProject1() method, then it
> >> should work:
> >>
> >> /**
> >>  * @flexjsignorecoercion MyButton
> >>  */
> >> >public function WebProject1() {
> >> >var button : MyButton = document.createElement("button") as MyButton;
> >> >button.innerHTML = "Press Me";
> >> >document.body.appendChild(button);
> >> >}
> >> >}
> >> >}
> >>
> >
> >That kind of worked.  Compiles fine and creates the button.  But
> >MyButton's
> >constructor does not get called.  Any code I write inside MyButton.as
> >seems
> >to be moot.
> >
> >I'm wondering if document.createElementNS might be useful here?
>
> Well, I doubt it.  IMO, you are trying to mix scripting APIs with
> object-oriented APIs.  Just like you wouldn't create a plain button by
> calling "new HTMLButtonElement()", you have to pick a pattern and stick
> with it.
>
> The FlexJS framework components internally call createElement for you and
> wrap the HTMLButtonElement since you can't actually subclass it and
> instantiate it.  If HTML had an extensible component/element API we
> probably wouldn't have bothered to create FlexJS.
>
> Then you can use all object-oriented APIs/patterns since that's what we're
> used to in ActionScript/Flash.  I suppose you could create another
> component set that even more thinly wraps HTMLButtonElement than we do
> already, and then make "new HTMLButtonElement()" work.  I've chosen to
> pack a bit more in org.apache.flex.html.Button so it can have more
> Flex-like APIs
>
> -Alex
>


Turns out that WebComponents provides exactly these kinds of APIs.  And
they seem to be working (almost) fine with FlexJS/Falcon :-)

Here is how I am making this work:

MyButton.as

package {
public class MyButton extends HTMLButtonElement {
public function MyButton(label) {
super();
}
public function createdCallback() {
    var sr = this['createShadowRoot'](); //TODO:FIXME
HTMLElement.createShadowRoot is typed to be an Object instead of a Function
sr.innerHTML = 'Click Meeee';
}
}
}

WebProject1.as

package {

public class WebProject1 {
public function WebProject1() {
var MyButtonClass = document['registerElement']('my-button', { //TODO:FIXME
HTMLElement.registerElement is typed to be an Object instead of a Function
 prototype: Object['create'](MyButton['prototype']), //TODO:FIXME
Object.create and Object.prototype is missing
 'extends': 'button'});

var button = new MyButtonClass();
button.addEventListener("click", button_clickListener,false);
document.body.appendChild(button);
}
private function button_clickListener(event : MouseEvent) : void {
alert("Hello World");
}
}
}

A few things to note:

1.  The extended component has a few lifecycle methods; createdCallback
being one.  All code that usually goes in the Constructor should go in
here.
2.  Before instantiating the new component, a call to
document.registerElement should be made.
3.  Works only one Chrome and Firefox (need to enable WebComponents in
chrome://flags/#enable-experimental-web-platform-features and Firefox:
about:config, dom.webcomponents.enabled)
4.  Seems like MS Edge and Safari will be supporting this soon:
http://caniuse.com/#feat=shadowdom

I don't know how useful all this is, but is very cool that we can support
WebComponents out of the box.

I am going to experiment more with this!

Thanks,
Om

Re: [FlexJS] Extending builtin HTML elements

Posted by Alex Harui <ah...@adobe.com>.

On 1/6/16, 11:36 PM, "omuppi1@gmail.com on behalf of OmPrakash Muppirala"
<omuppi1@gmail.com on behalf of bigosmallm@gmail.com> wrote:

>>
>> Add the following as the ASDoc for the WebProject1() method, then it
>> should work:
>>
>> /**
>>  * @flexjsignorecoercion MyButton
>>  */
>> >public function WebProject1() {
>> >var button : MyButton = document.createElement("button") as MyButton;
>> >button.innerHTML = "Press Me";
>> >document.body.appendChild(button);
>> >}
>> >}
>> >}
>>
>
>That kind of worked.  Compiles fine and creates the button.  But
>MyButton's
>constructor does not get called.  Any code I write inside MyButton.as
>seems
>to be moot.
>
>I'm wondering if document.createElementNS might be useful here?

Well, I doubt it.  IMO, you are trying to mix scripting APIs with
object-oriented APIs.  Just like you wouldn't create a plain button by
calling "new HTMLButtonElement()", you have to pick a pattern and stick
with it.

The FlexJS framework components internally call createElement for you and
wrap the HTMLButtonElement since you can't actually subclass it and
instantiate it.  If HTML had an extensible component/element API we
probably wouldn't have bothered to create FlexJS.

Then you can use all object-oriented APIs/patterns since that's what we're
used to in ActionScript/Flash.  I suppose you could create another
component set that even more thinly wraps HTMLButtonElement than we do
already, and then make "new HTMLButtonElement()" work.  I've chosen to
pack a bit more in org.apache.flex.html.Button so it can have more
Flex-like APIs

-Alex


Re: [FlexJS] Extending builtin HTML elements

Posted by OmPrakash Muppirala <bi...@gmail.com>.
On Wed, Jan 6, 2016 at 8:54 PM, Alex Harui <ah...@adobe.com> wrote:

> On 1/6/16, 6:35 PM, "Andy Dufilie" <an...@gmail.com> wrote:
>
> >button is null because document.createElement("button") is not an instance
> >of MyButton.
>
> Andy is right.  We have not tried to extend the type system into the
> built-in classes.  Not sure we could guarantee that would work.  More
> below...
>
>
> >Is this supposed to work?
> >
> >MyButton.as
> >package {
> >public class MyButton extends HTMLButtonElement {
> >public function MyButton() {
> >super();
> >this.addEventListener("click", button_clickListener, false);
> >}
> >private function button_clickListener(event : MouseEvent) : void {
> >alert("Hello World");
> >}
> >}
> >}
> >
> >WebProject1.as
> >package {
> >public class WebProject1 {
>
> Add the following as the ASDoc for the WebProject1() method, then it
> should work:
>
> /**
>  * @flexjsignorecoercion MyButton
>  */
> >public function WebProject1() {
> >var button : MyButton = document.createElement("button") as MyButton;
> >button.innerHTML = "Press Me";
> >document.body.appendChild(button);
> >}
> >}
> >}
>

That kind of worked.  Compiles fine and creates the button.  But MyButton's
constructor does not get called.  Any code I write inside MyButton.as seems
to be moot.

I'm wondering if document.createElementNS might be useful here?

Thanks,
Om

Re: [FlexJS] Extending builtin HTML elements

Posted by Alex Harui <ah...@adobe.com>.
On 1/6/16, 6:35 PM, "Andy Dufilie" <an...@gmail.com> wrote:

>button is null because document.createElement("button") is not an instance
>of MyButton.

Andy is right.  We have not tried to extend the type system into the
built-in classes.  Not sure we could guarantee that would work.  More
below...


>Is this supposed to work?
>
>MyButton.as
>package {
>public class MyButton extends HTMLButtonElement {
>public function MyButton() {
>super();
>this.addEventListener("click", button_clickListener, false);
>}
>private function button_clickListener(event : MouseEvent) : void {
>alert("Hello World");
>}
>}
>}
>
>WebProject1.as
>package {
>public class WebProject1 {

Add the following as the ASDoc for the WebProject1() method, then it
should work:

/**
 * @flexjsignorecoercion MyButton
 */
>public function WebProject1() {
>var button : MyButton = document.createElement("button") as MyButton;
>button.innerHTML = "Press Me";
>document.body.appendChild(button);
>}
>}
>}

I've pondered other ways to tell the compiler to not actually generate the
type-checking code since it doesn't actually get used at runtime by the
runtime.  Lots of options here:

1) Extend the type system by adding FLEXJS_CLASS_INFO to existing classes
2) Use @flexjsignorecoercion
3) Automatically suppress type-checking code for all external definitions
4) Compiler options to suppress type-checking
Etc.

-Alex


Re: [FlexJS] Extending builtin HTML elements

Posted by Andy Dufilie <an...@gmail.com>.
button is null because document.createElement("button") is not an instance
of MyButton.
Is this supposed to work?

MyButton.as
package {
public class MyButton extends HTMLButtonElement {
public function MyButton() {
super();
this.addEventListener("click", button_clickListener, false);
}
private function button_clickListener(event : MouseEvent) : void {
alert("Hello World");
}
}
}

WebProject1.as
package {
public class WebProject1 {
public function WebProject1() {
var button : MyButton = document.createElement("button") as MyButton;
button.innerHTML = "Press Me";
document.body.appendChild(button);
}
}
}

This code compiles fine, but when I run it, I am getting a null for
variable button.
Console log:
Uncaught TypeError: Cannot set property 'innerHTML' of null

Thanks,
Om