Table rowspan and colspan issue in Internet Explorer and Edge

1,137 views
Skip to first unread message

Róbert Gölle

unread,
Apr 6, 2016, 11:15:38 AM4/6/16
to Elm Discuss
Hello,

We have an issue with rendering table colspan and rowspan attributes in Internet Explorer and Edge. In the test app you can click 2 buttons (click them more then once) and you can see the problem.

The same code works fine in Firefox and Chrome.

Test application:
https://github.com/majorimi/ElmTableBug 

Thanks,
Robert

Gábor Varga

unread,
Apr 6, 2016, 1:56:34 PM4/6/16
to Elm Discuss
To give this a little context, the underlying problem here is that the current Virtual-DOM implementation handles the colspan and rowspan attributes as string attributes. 

According to W3C specs (https://w3c.github.io/html/tabular-data.html#attributes-common-to-td-and-th-elements) this should not be the case though, colspan
and rowspan can only hold non-negative integer values.

Non-negative integers are defined in https://w3c.github.io/html/infrastructure.html#valid-non-negative-integer as "a string [...] if it consists of one or more ASCII digits."

When these attributes are removed from the DOM, their value is set to "" -- which, in my opinion does not comply with the specs above and that's why we get these errors in some browsers. Now, this might relate to the ambiguity around so-called IDL attributes (https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes#Content_versus_IDL_attributes), and the way elm (0.16) is setting these JavaScript Properties/HTML attributes using a string value instead of the number representation directly.

I would also like to add that I experienced problems in Firefox as well, not just MSFT browsers. Maybe it was a previous version of the browser or a more complex scenario than the one in the sample app.

Evan Czaplicki

unread,
Apr 6, 2016, 5:33:24 PM4/6/16
to elm-d...@googlegroups.com
We know that "" does not remove the attribute, so what value must be given instead to get the desired result? You should be able to test this just in JS with no Elm things at all.

For example, if you set it like this:

domNode.colspan = null;

What happens? Is the attribute properly removed? If null does not work, what does?

Basically, we need to know what IE considers "valid" values for each scenario.

--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Gábor Varga

unread,
Apr 7, 2016, 1:00:33 AM4/7/16
to Elm Discuss
I tried it out briefly and found that IE and Edge are both very strict in this case. If the property requires an integer, they only accept that, nothing else: "" and null both fail.
Only node.removeAttribute(propName) would work.

I added some logging to the removeProperty function to see what is going on, and also made some changes to make it IE compatible for the example.

I have the following questions on my mind:
  1. Why pass colspan, rowspan and any other numeric attributes as strings, when they will be converted to number anyway (this happens in Elm)?
  2. Why use  "... } else if (typeof previousValue === "string") { ..." instead of "... } else if (typeof node[propName] === "string") { ..."? The later one checks the real type of the property instead of the type that was used to set the value of the property (see the IDL attributes ref I sent before) and this is true in all browsers, since all of them (including Chrome) would return number in the later case while the first case will always be string.
  3. Why exactly are there these specific branches when, in my understanding, node.removeAttribute(propName) should always work?


I am on vacation right now as you know, but I can put together a JSfiddle next week to capture the gist of all this.

Evan Czaplicki

unread,
Apr 7, 2016, 11:08:24 PM4/7/16
to elm-d...@googlegroups.com
The root thing is that Properties and Attributes do not overlap 100% in JavaScript. It is described in more depth here.

It sounds like you can switch to defining your own versions of colspan and rowspan as attributes (instead of properties) and see if they work:

import Html.Attribute as A

colspan : Int -> Attribute
colspan n =
  A.attribute "colspan" (toString n)

rowspan : Int -> Attribute
rowspan n =
  A.attribute "rowspan" (toString n)

Let me know how these work on IE Edge. If it's good, can you test on all the other browsers you have access to and let me know the exact results? (Browser, version, OS, etc.)

Róbert Gölle

unread,
Apr 8, 2016, 11:40:21 AM4/8/16
to Elm Discuss
They work fine in IE & Edge. We will send detailed browser test results soon.

Gábor Varga

unread,
Apr 9, 2016, 12:00:17 AM4/9/16
to Elm Discuss
While the guys produce the test results let me follow up on the more theoretical aspect of this discussion. 


Other than it being a rainy day in LA anyway, I hope that this discussion can benefit the community in the longer term and can lead to getting this fundamental part of the framework right.

"The root thing is that Properties and Attributes do not overlap 100% in JavaScript." -- I aggree.
But what are these "Properties" exactly and how are they supposed to work? My understanding is that they are vendor specific implementation of what Mozilla calls "IDL attributes". 
And the closest spec I could find which describes how these "Properties"/"IDL attributes" should work is this one: https://html.spec.whatwg.org/multipage/infrastructure.html#reflecting-content-attributes-in-idl-attributes

Generally my impression is that these "IDL attributes" are only there for convenience reasons, so it is easier to manipulate DOM attributes directly in JavaScript. Their behavior is not clearly specified and consequently the implementations are also rather unpredictable.

The main differences in my understanding are the followings:
  1. The value of a DOM attribute is always of type string -- vs -- the "JavaScript Properties" / "IDL attributes" on the other hand can have several types including boolean, long, non/negative integer etc.
  2. You can set a the value of a DOM attribute using any arbitrary string, without getting a JS exception, it will default to something defined by the HTML standard for invalid values -- vs -- setting the "JavaScript Properties" / "IDL attributes" can, by definition, result in JavaScript exceptions.
  3. You can explicitly remove a DOM attribute -- vs -- depending on the type of the particular  "JavaScript Property" / "IDL attribute", setting them to particular values should result in the removal of the attribute. 
    But it can be very unpredictable: for instance setting maxLength on an input to "" or null will set it to 0 instead of removing it -- on all browsers (Edge/Firefox/Chrome).
    Here is a sample Elm app that exposes this problem: https://github.com/gaborv/VirtualDomBug

In summary setting DOM attributes directly seems (to me) to work the same way as setting them in plain HTML whereas using JavaScript Properties is typical JavaScript behavior: it is going to work in 90% of the time.


With that in my mind, would you consider using DOM Attributes everywhere instead of JavaScript properties in the next version of elm-html -- like in the code sample you posted?


Evan Czaplicki

unread,
Apr 9, 2016, 2:53:42 AM4/9/16
to elm-d...@googlegroups.com
I'm no great expert on this. The default is properties mainly because that's what I saw other folks doing.

I'd say the next thing to consider would be: is there any performance improvement/penalty when you switch to attributes?

Gábor Varga

unread,
Apr 29, 2016, 11:26:00 AM4/29/16
to Elm Discuss
Quick update on this issue:

I put together a small JS test to benchmark the performance characteristics: https://github.com/gaborv/attributeVsProperty


My initial experience (running this on Chrome/Firefox/Edge/IE): using properties is usually somewhat quicker, but not always and not on every browser (Firefox specifically tends to favor attributes over properties for string values). What's more important is that using properties over attributes is significantly faster only when it does not work as desired: for Int values.
And even in this case the mixed approach would give us most of the performance advantage while providing the desired behavior. 
So my initial feeling about this is that the mixed approach (setting the value through property, but removing it using the removeAttribute() function) would yield the most predictable performance as well as behavior across browsers and in general.

I will put together a more comprehensive set of data from multiple platforms and browsers. 


In the mean time it is fun to give it a try. For me it was also interesting to see how Chrome kicked everyone out by being, we can say, an order of magnitude faster than Edge at the 2nd place, not to mention the rest.
Reply all
Reply to author
Forward
0 new messages