fromNative() does return an instance of TextField but nothing I set on it changes the element on the screen - so I think I'm passing in the wrong native object.
How do I query the HTML page for a native object that I may pass to Elem.fromNative()?
dom::Elem.fromNative() JS source code:
fan.dom.ElemPeer.fromNative = function(obj, type)
{
return fan.dom.ElemPeer.wrap(obj, type.make());
}
/*
* Native only method to wrap an existing DOM node. If this node
* has already been wrapped by an Elem instance, return the
* existing instance.
*/
fan.dom.ElemPeer.wrap = function(elem, fanElem)
{
if (elem == null) throw fan.sys.ArgErr.make("elem is null")
if (elem._fanElem != undefined)
return elem._fanElem;
if (fanElem && !(fanElem instanceof fan.dom.Elem))
throw fan.sys.ArgErr.make("Type does not subclass Elem: " + fanElem);
var x = fanElem || fan.dom.Elem.make();
x.peer.elem = elem;
elem._fanElem = x;
return x;
}
andySat 7 Dec 2019
All Fantom API's always return an instance of dom::Elem already.
When you need to use fromNative is when you are bridging with JavaScript:
So I can query the dom and bring back an arbitrary subclass of Elem (if it's not been mapped already).
With Doc.elemById being defined as:
native Elem? elemById(Str id, Type type := Elem)
Looking at the JS source, elemById() could be updated pretty easily to take the optional Type parameter:
fan.dom.DocPeer.prototype.elemById = function(self, id, type)
{
var elem = this.doc.getElementById(id);
if (elem == null) return null;
return fan.dom.ElemPeer.wrap(elem, type.make()); // <-- Only this line changes!
}
Although type.make() would need to be moved inside ElemPeer.wrap for performance reasons.
What do you think? Something like the above would really help integrate Fantom in to existing webpages.
SlimerDudeThu 12 Dec 2019
Hi, I've just noticed the @NoDoc Doc.querySelectorAllType(...) method which appears to be just what I was asking for:
// <input id="email" type="text">
text := doc.querySelectorAllType("#email", TextField#).first
But initial trials have had sporadic success; while I can change properties like val I don't seem to be able to change the styling.
Mmm... it maybe easier for now to write one's own wrapper classes around Elem that use composition over inheritance.
andyThu 12 Dec 2019
That doesn't quite work the way you probably want it to :)
DomKit is not always a 1:1 match to the raw HTML. So there is no official support for basically parsing HTML into DomKit. Which is I think is what you're after?
SlimerDudeFri 13 Dec 2019
Kindof, yes. I want to query different parts of HTML and manipulate it through domkit. While I realise it wouldn't be possible to utilise all of domkit in this way, it would have been useful to have access to the simple Form Inputs.
Using TextField as an example, this is the approach I've taken...
TextFields can still be created on the fly, ala domkit, but instances are cached on the Elem itself so any future queries on the HTML dom return the same objects.
using dom
@Js class TextField {
Elem elem { private set }
** Value of text field.
Str val {
get { elem->value }
set { elem->value = it }
}
private new _make(Elem elem) {
this.elem = elem
...
}
** The classic *domkit* ctor.
static new make() {
fromElem(Elem("input") {
it["type"] = "text"
})
}
** Wraps the queried Elem in a TextField.
static new fromSelector(Str selector) {
elem := Win.cur.doc.querySelector(selector)
if (elem == null) throw Err("Could not find TextField: ${selector}")
return fromElem(elem)
}
** Caches the TextField instance on the wrapped Elem.
static new fromElem(Elem elem) {
if (elem.prop(TextField#.qname) == null)
elem.setProp(TextField#.qname, TextField._make(elem))
return elem.prop(TextField#.qname)
}
...
...
...
}
andyFri 13 Dec 2019
I've been (very slowly) working on a "Fantom on Rails" framework -- and I know I am going to run up against this kind of stuff -- will be later next year (hopefully...) -- but I'll give some thought to how it might work.
SlimerDude Fri 6 Dec 2019
I was very excited to find
Elem.fromNative()
but I'm struggling to get it to work...I want to run Fantom code to alter an existing / already rendered webpage...
fromNative()
does return an instance ofTextField
but nothing I set on it changes the element on the screen - so I think I'm passing in the wrong native object.How do I query the HTML page for a native object that I may pass to
Elem.fromNative()
?dom::Elem.fromNative()
JS source code:andy Sat 7 Dec 2019
All Fantom API's always return an instance of
dom::Elem
already.When you need to use
fromNative
is when you are bridging with JavaScript:Here
fromNative
converts a "raw" DOM node into thedom::Elem
instance.SlimerDude Sat 7 Dec 2019
Hi Andy,
Thanks for the clarification - I've never really mixed Fantom and Javascript like that before.
So... I guess what I'm asking for then, is a method like this:
So I can query the dom and bring back an arbitrary subclass of
Elem
(if it's not been mapped already).With
Doc.elemById
being defined as:Looking at the JS source,
elemById()
could be updated pretty easily to take the optional Type parameter:Although
type.make()
would need to be moved insideElemPeer.wrap
for performance reasons.What do you think? Something like the above would really help integrate Fantom in to existing webpages.
SlimerDude Thu 12 Dec 2019
Hi, I've just noticed the
@NoDoc Doc.querySelectorAllType(...)
method which appears to be just what I was asking for:But initial trials have had sporadic success; while I can change properties like
val
I don't seem to be able to change the styling.Mmm... it maybe easier for now to write one's own wrapper classes around
Elem
that use composition over inheritance.andy Thu 12 Dec 2019
That doesn't quite work the way you probably want it to :)
DomKit is not always a 1:1 match to the raw HTML. So there is no official support for basically parsing HTML into DomKit. Which is I think is what you're after?
SlimerDude Fri 13 Dec 2019
Kindof, yes. I want to query different parts of HTML and manipulate it through domkit. While I realise it wouldn't be possible to utilise all of domkit in this way, it would have been useful to have access to the simple Form Inputs.
Using
TextField
as an example, this is the approach I've taken...TextFields can still be created on the fly, ala domkit, but instances are cached on the Elem itself so any future queries on the HTML dom return the same objects.
andy Fri 13 Dec 2019
I've been (very slowly) working on a "Fantom on Rails" framework -- and I know I am going to run up against this kind of stuff -- will be later next year (hopefully...) -- but I'll give some thought to how it might work.