-
Notifications
You must be signed in to change notification settings - Fork 178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SVGElement but not svg tag #313
Comments
Can you give me some examples?
You probably want it to look like this: fn owner_svg_element(&self) -> Option<SvgElement> {
js!(
return @{self.as_ref()}.ownerSVGElement;
).try_into().unwrap()
} where pub trait ISvgElement: IElement {
// ...
}
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "SVGElement")]
#[reference(subclass_of(EventTarget, Node, Element))]
pub struct SvgElement( Reference );
impl IEventTarget for SvgElement {}
impl INode for SvgElement {}
impl IElement for SvgElement {}
impl ISvgElement for SvgElement {} Basically, you're not supposed to return traits. |
If you compare elements - for extreme cases see the svg tag, the title tag and the discard tag, the only attributes all seem to have in common are the core attributes . Many elements have more attributes in common: styling attributes, global event attributes, presentation attributes and the conditional processing attributes. Graphics elements additionally have graphical event attributes. Most svg elements have element-specific attributes in addition to common groups of attributes. svg tag-specific attributes are baseProfile, contentScriptType, contentStyleType, height, preserveAspectRatio, version, viewBox, width, x, y. There are other elements that share some of these element-specific attributes. e.g. the view element shares preserveAspectRatio and viewBox. On a side note: Half of the element-specific attributes of svg element are deprecated. What is stdweb's policy on implementing deprecated and experimental tags and attributes?
So the alternatives are as follows
|
@NeverGivinUp The reason you can't return traits isn't because of stdweb, it's a limitation in Rust itself. Rust is statically typed, so everything must have a concrete type which is known at compile time. Even when you use things like So you will need concrete types for the various SVG elements, there is no way around that. As @koute mentioned, it's easy to create such types by using Each SVG element should be a distinct struct, using However, even though you can use So instead, in stdweb we use traits to simulate method/property inheritance (though there is a proposal to replace traits with Deref, you can ignore that for now). Basically, you use traits for methods which are shared between many types, and concrete methods for methods which exist only on a specific type. Let me give an example, so you can clearly see how we do things. You can then use the same techniques for SVG.
That is all that is needed to create a root type (such as Now let's look at how we can create sub-classes of
That's it! As you can see, creating a sub-class is very similar to creating a root class. Of course we can go deeper as well. Here is how the
It is the same as how we created The end result is:
If there are some methods which exist only on one specific type, we just use normal inherent methods: Lines 366 to 396 in ac96613
As for deprecated methods, we generally don't add them in unless there is a very good reason to do so. We're more accepting of experimental methods, though it needs to be clear in the documentation where they are supported (and where they're not supported). Does that answer your questions? Is there anything which is still not clear? |
P.S. There are some methods which are defined as mixins, so they don't belong to a particular class. In that case we use this technique:
|
Thank you @Pauan, for the detailed explanation. It has been very helpful. And thank you @Pauan, too. And merry Christmas, to you (if you are christian or just like the festivities). It seems my confusion mainly stemmed from naively equalizing Javascript interfaces with Rust traits. Instead in StdWeb I need to represent a Javascript Interface it by a Rust struct, which references that Interface. A corresponding trait is purely for the convenient default implementations. It has nothing to do with the Javascript Interface. To represent a Javascript Interface separately from a Javascript Class I need to create separate Rust structs for each of them. Another confusion of mine was between SVGElement and SVGSVGElement. The former is the Javascript Interface from which all SVG elements inherit. The latter is the Javascript Interface to the svg tag element. I'm obviously a rookie, when it comes to modern web development. Most developers that currently use StdWeb have a solid Javascript and WebApi background. In time more developers will use StdWeb, that are not as familiar with them. Suppose they try to instantiate of SVGElement or HTMLElement. What is the idiomatic way to tell them to use SVGSVGElement or HTMLHtmlElement instead? Documentation? An explicit check (and error) in document().create_element() and document().create_element_ns()? |
Yeah, you too.
WebIDL interfaces are actually the same as JavaScript classes (i.e. concrete types). They're not interfaces at all (even though they're called interfaces). WebIDL mixins are more like interfaces (and they map cleanly to Rust traits). Yes, it's confusing.
Yes, though it's more precise to say that the Rust struct corresponds to the JavaScript class while the Rust trait corresponds to the JavaScript methods. The other reason is to allow for method/property inheritance (e.g. you can create a method which accepts
Yes, each interface corresponds to a separate Rust struct. Except a WebIDL interface is the same as a JavaScript class, they're not separate things. So a Rust struct corresponds to a JavaScript class (which is the same as a WebIDL interface).
Yes, it's quite confusing. As you figured out,
That's not a problem, we can help fill in any missing gaps and answer questions.
This is done using let x: InputElement = document().create_element("input").unwrap().try_into().unwrap(); Or for SVG elements: let x: SvgPathElement = document().create_element_ns("http://www.w3.org/2000/svg", "path").unwrap().try_into().unwrap(); The type ( If you create an app, I recommend creating helper functions to make the above easier: fn create_element<A>(tag: &str) -> A where A: TryFrom<Element> {
document().create_element(tag).unwrap().try_into().unwrap()
} let x: InputElement = create_element("input"); Or perhaps using a DOM framework like dominator. There's actually quite a few DOM frameworks available for Rust (including Virtual DOM ones like yew) |
Oh, I just now realized I didn't really answer your question.
Since the JavaScript runtime class is determined by the tag (not the type), it is perfectly valid to create an It won't give an error, but of course you'll only be able to use the If you want to use Maybe we could use some documentation for that. Or perhaps instead we could create something similar to let x: SvgSvgElement = document().create_element().unwrap(); I like that idea a lot. I should implement that in dominator. |
Thanks again @Pauan! I managed to get a stub implementation of SVGSVGElement working. When I create it like this (I am aware, that in practice I'll need something like a namespace handle and can't just write an attribute):
I get
The xlink namespace, i added manually, is there. The svg namespace is missing. Do you happen to know if this is
|
@NeverGivinUp In the browser debugger tools it doesn't show the namespace, but it really is there. You can verify this by selecting the |
I'm just going to believe you. Thanks @koute ! |
I'm considering implementing some svg api, but my rust and stdweb knowledge is insufficient. Help me out, please.
SVGElement is the interface all elements in the svg namespace implement. It provides functionality similar to the INode interface. Notably the ownerSVGElement function returns an Option of a SVGElement similar to the parentElement function of the Node interface. The return type of parent_element in Stdweb is Option< Element >, though "The parent of an element is an Element node, a Document node, or a DocumentFragment node." (Source). This works, I suppose, because Document and DocumentFragment can, for all practical purposes, be considered the html tag element or another element. In the SVG case this is not possible. The svg tag element does have attributes some, but not all other elements share. Thus it cannot be considered a super type of all other tags in the svg namespace. So ownerSVGElement cannot return Option but must return Option.
The function owner_svg_element of the trait
ISVGElement: IElement
errors as follows
The same for
fn viewport_element(&self) -> Option<ISVGElement>
, which is the more relevant, as not all elements have a viewport, but the svg tag element as well as some other elements do.If I change the signature to
the error changes to
The text was updated successfully, but these errors were encountered: