how to extend javascript extern class?

144 views
Skip to first unread message

Steve Jeon

unread,
Jul 21, 2014, 6:17:50 AM7/21/14
to haxe...@googlegroups.com
Hi, 

It seems similar topic down there, but not related to my question.
Basically, I'd like to do dynamically add subclass of javascript extern class (js.html.DivElement) like below..
Is there any practical way to do this?

//

class Main {
 
Browser.window.onload = function(e:EventListener):Void {
   
var tmpBox:Box = new Box();
       tmpBox.setSize(100, 100);
       Browser.document.body.appendChild (tmpBox);   


 
}
}


class Box extends js.html.DivElement implements IResizable {
        public function new () {
            // Actually can't do 'super()' as DivElement doesn't have constructor.. I get it.., but I can't figure it out how to achieve what I want..
           
//super();    
 
}

 
 
/* INTERFACE model.IResizable */
 
 
public function setSize(w:Int, h:Int):Void
  {
            this.style.width = w+"px";
           
this.style.height = h+"px";
       
}
}



Juraj Kirchheim

unread,
Jul 21, 2014, 6:29:54 AM7/21/14
to haxe...@googlegroups.com
The thing is that `js.html.DivElement` is natively called
`HTMLDivElement` and if you look at the spec, you will find that it is
an interface rather than a class (which is erroneously mapped in the
std lib) and you cannot call the constructor. You create divs through
`document.createElement()` (or through parsing HTML).

There are probably some clever hacks that might work in some browser
or another, but I suggest you just use composition.

Best,
Juraj

Porfírio Ribeiro

unread,
Jul 21, 2014, 5:20:21 PM7/21/14
to haxe...@googlegroups.com
Unfortunately you can't extend native html classes that way.

Elements must be created with document.createElement()

Unless you use the new webcomponents api: http://www.html5rocks.com/en/tutorials/webcomponents/customelements/

There are some polyfils available like Polymer or Mozilla x-tags.

I am doing some research and some work on this subject right now! I am trying to make it possible to define those custom elements easily in Haxe. 


ATM what you can do is have your class to wrap the real element and access it as a var to add it to document.

Porfírio Ribeiro

unread,
Jul 21, 2014, 5:32:09 PM7/21/14
to haxe...@googlegroups.com
Or you may also use an abstract to wrap it arround like this
@:forward
abstract Box(js.html.DivElement) to js.html.DivElement {
   
public inline function new(){
       
this = untyped js.Browser.document.createDivElement();
   
}

     
public inline function setSize(w:Int, h:Int):Void {

       
this.style.width = w+"px";
       
this.style.height = h+"px";
   
}
}

Then use it like:
        var box=new Box();
        box
.setSize(100,100);
        box
.innerHTML="Text";
        document
.body.appendChild(box);


Steve Jeon

unread,
Jul 21, 2014, 11:20:46 PM7/21/14
to haxe...@googlegroups.com
I really appreciate for the sample code. It was big help.  Now try to catch up about the keywords abstract and inline that you used. 
Although, I have experience with AS3, these are pretty new to me.  Besides, how do you call the thing you used.. like the '@:forward' ? 
I want to find further information about it. Again, many thanks.  :) 

Steve Jeon

unread,
Jul 21, 2014, 11:28:19 PM7/21/14
to haxe...@googlegroups.com
This haxe community is great. it's getting more clear now.
Thank you Juraj for kind answer.  

Simon Krajewski

unread,
Jul 22, 2014, 1:46:10 AM7/22/14
to haxe...@googlegroups.com
Am 22.07.2014 05:20, schrieb Steve Jeon:
I really appreciate for the sample code. It was big help.  Now try to catch up about the keywords abstract and inline that you used. 
Although, I have experience with AS3, these are pretty new to me.  Besides, how do you call the thing you used.. like the '@:forward' ? 
I want to find further information about it. Again, many thanks.  :)

Abstract types in Haxe are used similar to classes at compile-time, but turn into a different type at runtime. In this example you can treat Box as if it were a class (for the most part) and then the compiler will use js.html.DivElement when translating the code to Javascript. More information is available here: http://haxe.org/manual/types-abstract.html

@:forward is metadata. You can add metadata to any type or field and some of them influence compiler behavior. This particular one causes the compiler to forward field access on your abstract to its underlying type automatically, thus exposing its fields. See http://haxe.org/manual/types-abstract-forward.html

Simon




On Tuesday, July 22, 2014 5:32:09 AM UTC+8, Porfírio Ribeiro wrote:
Or you may also use an abstract to wrap it arround like this
@:forward
abstract Box(js.html.DivElement) to js.html.DivElement {
   
public inline function new(){
       
this = untyped js.Browser.document.createDivElement();
   
}

     
public inline function setSize(w:Int, h:Int):Void {
       
this.style.width = w+"px";
       
this.style.height = h+"px";
   
}
}

Then use it like:
        var box=new Box();
        box
.setSize(100,100);
        box
.innerHTML="Text";
        document
.body.appendChild(box);


--
To post to this group haxe...@googlegroups.com
http://groups.google.com/group/haxelang?hl=en
---
You received this message because you are subscribed to the Google Groups "Haxe" group.
For more options, visit https://groups.google.com/d/optout.

Juraj Kirchheim

unread,
Jul 22, 2014, 6:15:34 AM7/22/14
to haxe...@googlegroups.com
It is also worth noting that static extension might do the job:
http://haxe.org/manual/lf-static-extension.html

```
class ElementTools {
static public function setSize(e:js.html.Element, w:Int, h:Int) {
e.style.width = w + 'px';
e.style.height = h + 'px';
return e;
}
}

using ElementTools;

someDiv.setSize(100, 100);
```

Of course this depends on what you're really after.

Best,
Juraj

Steve Jeon

unread,
Jul 23, 2014, 6:06:00 AM7/23/14
to haxe...@googlegroups.com
Hi, Juraj

Today I tried this method as well, it seems working very well.
It seems in order to use "using", I have to make separated class file, right?
Anyway, thank you for nice tip.  

Best,
Steve

Juraj Kirchheim

unread,
Jul 23, 2014, 6:21:47 AM7/23/14
to haxe...@googlegroups.com
On Wed, Jul 23, 2014 at 12:05 PM, Steve Jeon <etul...@gmail.com> wrote:
> It seems in order to use "using", I have to make separated class file,
> right?

No, but rather than using the the class that provides the static
extensions, you have to be using the module (i.e. the haxe file) that
defines that class. Here is an example: http://try.haxe.org/#26843
(the module's name is hard coded to "Test" on try.haxe.org).

Best,
Juraj
Reply all
Reply to author
Forward
0 new messages