Change proposal for the DOM API

64 views
Skip to first unread message

Pierre Quentel

unread,
May 22, 2018, 2:30:27 AM5/22/18
to brython
In issue #829 Andy Lewis has reported a problem with HTML and SVG attributes. Trying to solve this issue made me realize that the way Brython manages attributes should be improved.

Background : attributes and properties

This is what I understand after reading things on the Internet (this post on stackoverflow in particular). Please correct me if I'm wrong.

While Python defines object attributes, that are managed by the syntax "element.attr_name", the DOM defines two different concepts for elements :
  • attributes, which are defined in the HTML (or SVG) tag : <img src="icon.png"> defines the attribute "src". The DOM specification defines a set of methods to manage attributes : getAttribute(name), setAttribute(name, value), etc.
  • properties, managed by the same dotted syntax as Python : element.attr_name
To make things more obscure, there is a link between some attributes and some properties. Generally, for the attributes that are expected for a given tag (eg "id" or "class" for any kind of tag, "src" for IMG tags, "href" for A, etc), when the attribute is set, the property is also set. Most of the time, the property name is the same as the attribute name, but there are exceptions : the property for the attribute "class" is "className". Generally, the property value is the same as the attribute value, but not always : for instance, for an element defined by <INPUT type="checkbox" checked="checked">, the value of attribute "checked" is "checked", and the value of property "checked" is the boolean "true".

Besides the attributes defined by the specification for a given tag, custom attributes can be defined (template engine use this a lot) ; for these attributes, the property of the same name is not set. Custom properties can also be defined for an element, and this doesn't set the attribute of the same name.

Attribute values are always strings, while property values can be of any type. Attributes are case-insensitive for HTML elements and case-sensitive for SVG elements ; properties are always case-sensitive.

Management in Brython

So far, the DOM API in Brython tries to manage both attributes and properties with the same syntax : "element.attr_name = value" or "value = attribute.name". Depending on the case, it's sometimes the attribute or the property which is set or read. Since the attributes or properties that are the most often used are "reflected" in each other, the confusion has little consequences, and in more than 5 years, few issues have been reported, but this lack of control on what is managed by the program is not a good thing.

Proposal

After a few experiments, the current development version proposes to manage properties with the syntax "element.attr_name", and attributes with a new attribute of DOMNode instances : "element.attrs". This attribute is a dict-like object:

element.attrs[name] = value
value = element.attrs[name]
delete element.attrs[name]
for name, value in element.attrs:
    ...

This proposal would certainly break existing code in some cases : for instance, setting the attribute "stroke" of an SVG element was possible with "element.stoke = value" and would now require "element.attrs["stroke"]  = value". But in practise, all the examples in the gallery and the demo work unmodified, so the consequences should be limited.

You can test this modified API by cloning the repository. Feedback is appreciated !

Glenn Linderman

unread,
May 22, 2018, 2:42:17 AM5/22/18
to bry...@googlegroups.com
On 5/21/2018 11:30 PM, Pierre Quentel wrote:
Proposal

After a few experiments, the current development version proposes to manage properties with the syntax "element.attr_name", and attributes with a new attribute of DOMNode instances : "element.attrs". This attribute is a dict-like object:

element.attrs[name] = value
value = element.attrs[name]
delete element.attrs[name]
for name, value in element.attrs:
    ...

This proposal would certainly break existing code in some cases : for instance, setting the attribute "stroke" of an SVG element was possible with "element.stoke = value" and would now require "element.attrs["stroke"]  = value". But in practise, all the examples in the gallery and the demo work unmodified, so the consequences should be limited.

You can test this modified API by cloning the repository. Feedback is appreciated !

For attributes with legal Python names, it would be handy to also permit:

element.attrs.name = value
value = element.attrs.name


Kiko

unread,
May 22, 2018, 3:41:41 AM5/22/18
to bry...@googlegroups.com

2018-05-22 8:42 GMT+02:00 Glenn Linderman <v+py...@g.nevcal.com>:
On 5/21/2018 11:30 PM, Pierre Quentel wrote:
Proposal

After a few experiments, the current development version proposes to manage properties with the syntax "element.attr_name", and attributes with a new attribute of DOMNode instances : "element.attrs". This attribute is a dict-like object:

element.attrs[name] = value
value = element.attrs[name]
delete element.attrs[name]
for name, value in element.attrs:
    ...

This proposal would certainly break existing code in some cases : for instance, setting the attribute "stroke" of an SVG element was possible with "element.stoke = value" and would now require "element.attrs["stroke"]  = value". But in practise, all the examples in the gallery and the demo work unmodified, so the consequences should be limited.

You can test this modified API by cloning the repository. Feedback is appreciated !

I'm +1 for the proposal but I would try to provide a deprecation cycle warning users that the old behaviour will be deprecated in version x.y.z and they should use the new one or avoid updates to do not break their apps/codes.

Andy Lewis

unread,
May 22, 2018, 9:54:11 AM5/22/18
to brython
Thank you Pierre for the brilliantly clear explanation of attributes and properties in HTML, SVG and the DOM.  These words are used in a slightly different way in a Python context, so the difference was unclear to me before.

I am feeling a little guilty for raising this issue, after the existing system has produced few problems in over 5 years.  However, from my perspective as a user, the proposed change is easily managed.

In simple terms (correct me if I am wrong Pierre, but this is what my testing indicates), if an attribute/property can be read or set using element.attr_name in Javascript, it will still be possible to do so in Brython (the new syntax will be available, but not necessary).  But if in Javascript it was necessary to use element.setAttribute(attr, value), then the element.attr_name=value syntax will no longer work in Brython, and the new syntax will be needed.

Of course we already have the convenience of the additional attributes listed in the Brython documentation. (I assume these will not change?)

Of the 114  HTML attributes listed here, the only ones I am likely to want to read, set, or change in Brython code are: action checked class href id name src style value . I have tested all these, and the
element.attr_name=value syntax works in all these cases.  So for me, no change is needed to any of my code which uses HTML elements.

For the SVG attributes, it is necessary in Javascript to use
element.setAttributeNS("null", attr, value), so as Pierre says, in Brython, for example element.stroke = value will no longer work.  But as explained here, for styling attributes in SVG, it is possible to use CSS syntax, so element.style.stroke = value does work. So my solution is to add an extra .style to code which sets those attributes (an easy find and replace), and to use Pierre's new syntax for attributes such as viewbox which are not styling attributes. Since I mostly access svg elements through my own module of classes subclassed from the svg classes, very little change has been needed to my code to get my projects working using the current master, nearly all the changes being in this one file.

So I am very happy for this change to go ahead, but as Kiko says, it will need to be flagged up well in advance, because other people could have more extensive codebases to maintain (I have only ~2500 lines across all my projects).

Enormous thank you to Pierre for all the work he has put into this!

Andy

Andy Lewis

unread,
May 22, 2018, 10:07:19 AM5/22/18
to brython
Hi again

Rather irrelevantly, does anyone know how to edit a post after it has been sent to the group?  I carefully changed the font of all the bits of code in my post, and as soon I clicked "Post", half of them changed back again! :-(

Andy

Pierre Quentel

unread,
May 23, 2018, 7:18:57 AM5/23/18
to brython
Thanks for the feedback !

@Glenn : I don't agree that element.attrs.name should be the same as element.attrs["name"] ; it's too Javascript-ish for me and not enough Pythonic. What do others think ?

@Kiko : in commit f8fad55 I have added warnings when a program tries to set an attribute which is defined as a read-only property in the element's prototype (for instance setting svg_element.cx = 100), or an attribute which is in fact an attribute of style (eg svg_element.fill = "blue" instead of svg_element.style.fill = "blue").

@Andy : yes, the Brython-specific attributes are not modified with these changes.

Unless other objections are raised, I will include these changes in the next release.

Reply all
Reply to author
Forward
0 new messages