Re: [FlexJS] Extending builtin HTML elements
On Wed, Jan 6, 2016 at 11:57 PM, Alex Harui wrote: > > > On 1/6/16, 11:36 PM, "omup...@gmail.com on behalf of OmPrakash Muppirala" > 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 M'; } } } 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
On 1/6/16, 11:36 PM, "omup...@gmail.com on behalf of OmPrakash Muppirala" 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
On Wed, Jan 6, 2016 at 8:54 PM, Alex Harui wrote: > On 1/6/16, 6:35 PM, "Andy Dufilie" 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
On 1/6/16, 6:35 PM, "Andy Dufilie" 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
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
[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