W3C home > Mailing lists > Public > www-style@w3.org > July 2008

Re: Parent Combinator / Parent pseudo-class

From: Andrew Fedoniouk <news@terrainformatica.com>
Date: Sat, 26 Jul 2008 13:59:47 -0700
Message-ID: <488B9043.8040205@terrainformatica.com>
To: Francois Remy <fremycompany_pub@yahoo.fr>
CC: "Tab Atkins Jr." <jackalmage@gmail.com>, Brad Kemper <brkemper@comcast.net>, Boris Zbarsky <bzbarsky@mit.edu>, www-style list <www-style@w3.org>

Francois Remy wrote:
> 
> From: "Andrew Fedoniouk" <news@terrainformatica.com>
>>
>> Tab Atkins Jr. wrote:
>>> On Fri, Jul 25, 2008 at 10:56 AM, Brad Kemper <brkemper@comcast.net 
>>> <mailto:brkemper@comcast.net>> wrote:
>>>
>>>
>>>     Consider the following:
>>>
>>>     div:with-child(code) { border:2px solid #999;
>>>     background-color:beige; }
>>>     div:with-child(code):before { content:"See Code:"; }
>>>
>>>     I would only want this on DIVs that surrounded the Code block
>>>     directly, not on any old DIV that happened to be an ancestor of
>>>     the code block.
>>>
>>>
>>> Nod, searching for just children would certainly be useful.  That's 
>>> why my proposal was for a simple selector preceded by a combinator.  
>>> You'd do this:
>>>
>>> div:matches( > code ) { border:2px solid #999; background-color:beige; }
>>> div:matches( > code ):before { content:"See Code:"; }
>> That is again subject of :root/:scope debate :)
>>>
>>>     I can really see no use case for a "has-child" pseudo-class to
>>>     look at all descendants.
>>>
>>>
>>> Really?  I can.  I probably wouldn't ever want to use a plain 
>>> descendant selector on something like a plain div, but I could easily 
>>> see this being used on a more complex element about which you have a 
>>> greater knowledge of it's use.  Frex:
>>
>> As a solution: http://www.terrainformatica.com/?p=100
> 
> CSS! is the most complex and most hypotetical proposal of the CSS WG...
> And, sorry but if it's to do something so, we can do it by JScript too.
> (and JScript is implemented in all browsers while CSS! in none)

You assume that CSS is only for browsers. That is quite narrow point of 
view. Installation base of applications that use DOM/CSS based UI is 
comparable with installation base of [installable] browsers.
Web browsers handle significantly bigger number of applications (if to 
consider web site as an application) but the number of instances of 
engines executing CSS far bigger than you think.

Far not of them have a luxury to run JS. For many reasons.

Static system of styles (classic CSS) has limitations that are
originated in its static nature.

Recent attempts to bring some dynamic attributes to it (variables, MQs)
are early birds. It will be more of those.

As an example: such typical static thing as Printing of HTML/CSS ideally
require dynamic features to exist in CSS.

Things like:

tfoot td.total-on-the-page
{
   replaced!: self:value = sum-of( $1(:current-page td.amount) );
}

are not available even for JS.

In UI task of styling things like:
http://terrainformatica.com/htmlayout/images/tree-view-checks.png
(checked/not-checked/mixed) belongs more to CSS(styling) than to
the logic i think.

Problems of computational complexity of static system of declarations
are in principle well known. Here is an example of static
transformation (XSLT):
http://www.tkachenko.com/blog/archives/000268.html
where procedural approach if it would exists reduces task
from O(n*n) to O(n).

> 
> document.querySelectorAll('li').forEeach(function (el) {
>    el.setAttribute('has-a-inside', el.querySelector('a') != null);
> });
> 
> And if there's a DOMModified event added to elements, we can do much 
> better :
> 
> function updateLI(el) {
>    el.setAttribute('has-a-inside', el.querySelector('a') != null);
> }
> 
> document.addEventListener("DOMNodeInserted", function(e) {
>    var el = e.target;
>    if (el.tagName=="A") {
>        while (el) {
>            if (el.tagName=="LI") {
>                updateLI(el);
>            }
>            el = el.parentNode;
>        }
>    }  else if (el.tagName=="LI") {
>        updateLI(el);
>    }
> });
> 
> document.addEventListener("DOMNodeRemoved", function(e) {
>    var el = e.target;
>    if (el.tagName=="A") {
>        while (el) {
>            if (el.tagName=="LI") {
>                updateLI(el);
>            }
>            el = el.parentNode;
>        }
>    }
> });
> 
> And we have [have-a-inside] maintained up-to-date....
> 

Pay attention that DOMNodeInserted shall be generated
for each element in the fragment that you insert.
So if you replacing content of the root node then
you will get N events and each of such event
executes el.querySelector('a') that is again O(N) complex.
So the total cost is O(N*N).


-- 
Andrew Fedoniouk.

http://terrainformatica.com
Received on Saturday, 26 July 2008 21:00:35 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Monday, 27 April 2009 13:55:10 GMT