Re: Proposal for limited :matches pseudoclass

From: "Eduard Pascual" <herenvardo@gmail.com>
Sent: Tuesday, January 20, 2009 5:33 PM
To: "François REMY" <fremycompany_pub@yahoo.fr>
Cc: "David Woolley" <forums@david-woolley.me.uk>; <www-style@w3.org>
Subject: Re: Proposal for limited :matches pseudoclass

>
> On Mon, Jan 19, 2009 at 8:39 PM, François REMY
> <fremycompany_pub@yahoo.fr> wrote:
>> I think it was already discussed about pros and cons of ":matches" 
>> selector.
>>
>> I wroted a document about it. It's only my vision of the situation, and 
>> you
>> may don't agree with me (please say it, if it's the case).
>> I hope this document is well-balenced and show the enormous advantages 
>> and
>> problems of the selector.
>> This document is not an essay about the problem, but I think it's a good
>> start to dicuss with full(er) knownledge about the subject.
>>
>> Fremy
>
> I have read your document and agree with most of the ideas it
> presents; but I think it misses some substantial points.
> Basically, it boilds down to "browser vendors should rewrite their
> browser's engines" which is probably a true fact, but it misses the
> point that "browser vendors will not rewrite their browser's engines
> (unless there is a compelling enough reason for them to do so, of
> course)", which is known to be a true fact. So the CSS WG has two ways
> to go: they can produce an utopic standard that offers the best
> solution to each problem, but will be useless because nobody will
> implement it; or they can produced a realistic standard which can't
> solve all the problems but at least solves some, and becomes
> implemented by enough parties for its solutions to be usable by
> authors.
> Although I would love to have the utopic standard implemented and use
> it on the content I publish; I have to stay in touch with reality. So
> I think we should try to get as near as possible to the utopy without
> taking off from reality. That's why I tried to figure out how much can
> be reasonably achieved before stepping into tough issues.

This is the biggest problem of CSS, and the web in general.
We always need to find the good middle between web-developers and 
implementors.
Implementors are developers, too, and they need stability, I'm conscient of 
that.

> It appears to me (please, someone correct me if I am wrong) that the
> main concern applies to page-loading, rather than arbitrary
> modifications from script: the current logics and limitations of CSS
> are optimal for any progressive rendering algorithm, so trying to
> break the essential limitations would affect adversely such
> algorithms. After all, during page loading browsers just add children
> to existing elements, one after another, so all the information needed
> to evaluate nowadays selectors for a given element is already
> available when the element is initially added. Once the page is
> loaded, modifications to the DOM are arbitrary (ie:
> adding/moving/removing stuff anywhere, compared to always adding
> "last-childs" during load), so something like a full :matches wouldn't
> really hurt: scripts can anyway tweak the class or id of the root
> element. Actually, if authors try to rely on javascript emulation of
> the :matches capability, the impact is even greater: not only does it
> do the same re-checking across the entire tree, but it is done through
> an interpreted language engine rather than natively. Hence, unless I'm
> missing something (please don't hesitate to point it out if you think
> I am), once the page has loaded a full :matches would have a positive
> impact, allowing the browser to natively perform styling tasks that
> would otherwise be handled by scripts.

It's my point of view, too.

> Putting it all together: ":matches" is horrible during loading; but
> it's not so bad (actually it's even good) after loading. Then simply
> ignore the ":matches" until the page is loaded. Or, in more formal
> words (these questions are addressed to implementors):
> - If the blocks containing ":matches" on their selectors were ignored
> during initial page loading, would the concerns still be there?
> - Would it be actually doable to skip such blocks during the initial
> loading, and "review" them once the page has been loaded?
>
> I'm eager to hear some implementors' voices on these two questions.

Wait and see.


=========================================================
NOTE : Here's the text of the quoted document, because it seems that it
was'nt transmitted to the W3C Group....
=========================================================

* Introduction
==============================
The developers need more complex behavior for CSS every day. This is because 
new web-based model is changing. While the website evolves and became more 
and more “used-editable”, a new type of web use is growing up: the rich 
internet application (also called RIA).

Theses sort of websites are behaving like any other applications, and this 
means that they need more ease of use, more speed in displaying and 
computing, and more facility to be written by the developers (because 
corporations needs the developers at others task than just front-end UI).

* Why do we need “:matches” ?
==============================
It’s clear that an element should be rendered in repercussion of its 
content. When the content is defined before the application runs, it’s easy 
for the developer to think about specific rules that matches some kind of 
elements. But since the content is more and more generated on basis of the 
client’s actions, it’s no more possible to predefine rules. Why then need 
dynamic rules. And it’s what we have with new selectors like ‘:checked’, 
‘:enabled’, ‘:not’, and pseudo-elements like ‘∷before’…  But it’s not 
sufficient. We need more control on the content of an element to determine 
which style we need to apply on it. This is why the “:matches” selector can 
be so useful.

* The problem of the implementation
==============================
I already talked about it; they are two possible way to match elements and 
CSS rules. You can either find all rules matching the element you’re using 
(and caching it, for more efficiency) and change the rules matched by an 
element based on the changes that are applied on it and elements that can 
have effect on it, or find elements based on the way the rules are defined, 
starting from the root of the document and finding each next possible 
matching step (this is how the brain does when writing the rules). For 
simplicity, I’ll later talk about ‘reversed way’ (the first one) and ‘normal 
way’ (the latter).

The first one seems to be implemented by the most browsers. Many reasons are 
advanced to explain this, and the primary one is that it’s simply smarter 
than the normal way and it should take less memory.

The reason of the gain of speed at is that it’s based on a simple fact “an 
element can change of style when a parent element is changed, or when the 
nextSibling chain have any change (including “:hover”, …). You can search, 
all currently implemented properties don’t need any other lookup for the 
runtime changes finding (even if some can be a bit slower with this method).

The problem of “:matches” is that it can change drastically this behavior. 
Actually, modifying a child element potentially can have effect on the whole 
DOM (as it was when you modified the class of the root element). Consider 
this simple situation:

:root:matches(error) *:not(error) { display:none; }

* How can we emulate the property?
==============================
Simply by doing what the browser don’t want to do self, watching for the 
whole DOM for some CSSRules.

Here’s a  ECMAScript implementation of the following rule [I don’t tested 
it] :

            error:matches(title) { display: block; }

var lastMatchedErrors = [];
addStyle("error.-auto-class-1 { display: block; }");

function onDOMChanged(e) {
 var matchedTitles = document.querySelector("error title");
    var newlyMatchedErrors = [];
    var newMatchedErrors = [];
    var current = null;
    for(i=0; current = matchedTitles[i]; i++) {
        while (current = current.parentNode) {
            if (current.tagName == "ERROR") {
                var CI = 0;
                if (CI = lastMatchedError.indexOf(current)==-1) {
                    newlyMatchedErrors.push(current);
                    newMatchedErrors.push(current);
                } else {
                    newMatchedErrors.push(current);
                    lastMatchedError[CI]=null;
                }
            }
        }
    }
    for (i=0; current=newlyMatchedElements[i]; i++) {
        current.className += " -auto-class-1";
    }
    var len = lastMatchedErrors.length;
    for (i=0; i!=len; i++) {
        if (current=lastMatchedErrors[i]) {
            current.className = current.className.replace("-auto-class-1", 
"");
        }
    }
    lastMatchedErrors = newMatchedErrors;
}


* What should the browsers do now?
==============================
It’s a difficult question. I’m in favor of a “:matches” implementation but I 
can accept concerns of browsers’ implementers. At the other side, I see both 
the benefice for the user and the developer, and an error of the 
implementers. By wanting more speed for the browsers, they have closed a lot 
of doors, and they must be aware that these doors will need to be opened, if 
not now, in a couple of years. Accepting the implementation of a “:matches” 
property, it’s not only a new selector that we introduce, but the acceptance 
of extending the whole CSS behavior. My thought is that the ‘normal way’ can 
be as fast as the ‘reversed way’, and can be simpler to implements. It was 
an error to do the things using another way. Complaining about speed 
problems is a false argument since editing the class of the root element 
also can change the whole DOM. But the things are the things, and developers 
must also be aware that creating and maintaining a browser is not easy. The 
change we’re querying can have great effect on browsers because, if it’s 
still possible to “hack” the current CSS model to support “:matches”, it’s a 
bad idea since it will make the support of latter CSS properties too complex 
because it will need another hacks.

* Draft specification (to be discussed)
==============================
<selector-1>:matches(<selector-2>)
1. Look all elements matching <selector-1>
2. For each element matched by <selector-1>, look at a child elements 
matching <selector-2>.
3. If a matching child element was found, the element found at 1. passes the 
:matches selector
4. Else, the element matched in 1. don’t pass the selector
 

Received on Tuesday, 20 January 2009 16:56:46 UTC