[whatwg] New method for obtaining a CSS property

On 1/28/2011 3:15 PM, Boris Zbarsky wrote:
> On 1/28/11 1:22 AM, Brett Zamir wrote:
>> My point is that a selector can be tied to a property through the
>> ruleset.
>
> No, not really.  Something that _matches_ selectors an be tied to a 
> property via seeing which selectors it matches and then considering 
> the resulting declaration lists....

Since I'm speaking more or less about a literal match, this would be 
basically the same as you are saying. In any case, I think you get my point.
>> I recognize there may be more than one declaration even with
>> the same property being associated with the same selector, but I'm
>> suggesting to define some rules for selecting the most logical match.
>
> So rules for matching selectors to selectors, right? 
Yes.
> Defining these could really get pretty complex, unless you're 
> suggesting that it just be a string compare of the serializations or 
> something.
Yes, I am suggesting the latter.

>>> You can do that right now using getComputedStyle, with a bit more
>>> code, right?
>>
>> Yes, or by iterating through document.stylesheets.
>
> Um... why would you do that?
>

Here's the way I've been doing it for my own code; remember all I want 
is the text of the property value associated with an exact selector 
match. With this function, I don't need to worry about context--just get 
the match I want (treating the passed selectorText argument like a 
variable name of an object and treating the passed propertyName as a 
property of that object).

function getCSSPropertyValue (selectorText, propertyName) {
     function _getPropertyFromStyleSheet (ss, selectorText, propertyName) {
         var rules = ss.cssRules ? ss.cssRules : ss.rules;
         for (var j = 0, crl = rules.length; j < crl; j++) {
             var rule = rules[j];
             try {
                 if (rule.type === CSSRule.STYLE_RULE && 
rule.selectorText === selectorText) {
                     return rule.style.getPropertyValue(propertyName);
                 }
             }
             catch (err) { /* IE */
                 if (rule.selectorText === selectorText) {
                     propertyName = propertyName.replace(/-([a-z])/g, 
function (str, n1) {
                         return n1.toUpperCase();
                     });
                     return rule.style[propertyName];
                 }
             }
         }
         return false;
     }
     for (var i = 0, value, dsl = document.styleSheets.length; i < dsl; 
i++) {
         var ss = document.styleSheets[i];
         value = _getPropertyFromStyleSheet(ss, selectorText, propertyName);
         if (value) {
             return value;
         }
     }
     return false;
}


>> But as Ashley pointed out, it is needlessly complex to create one's 
>> own pseudo document
>
> Why would you need to create a pseudo document?

Since my purpose is only to get the property value for an exact selector 
match, I'm not interested in getting a different match if a particular 
element say matches "E > F.class" rather than just "F.class". A user in 
such a use case does not care about, and probably doesn't want to face 
ambiguities raised by context.

>> for this purpose, and I think it should be a simple operation to be 
>> able to
>> do something as fundamental as following best practices.
>
> Ideally, yes, but setting styles directly from script (as opposed to 
> setting classes that are then styled by the stylesheet) is not exactly 
> "best practices", unless we're looking at different best practices lists.

Sometimes it is not possible to do this, which is the reason for this 
suggestion (even if CSS transitions could reduce the need for this 
somewhat):

var element = document.getElementById('start-transition'),
     successColor = getCSSPropertyValue('.transition-success', 
'background-color'),
     failureColor = getCSSPropertyValue('.transition-failure', 
'background-color');
indicateSuccessOrFail(element, successColor, failureColor);

function doFunkyTransition (element, beginColor, endColor) {
     // Base on RGB values of beginColor and endColor, incrementally
     // set the color style property of the element to the intermediate 
color
     // in whatever manner one wishes; more advanced cases could
     // be pulsating between colors, etc.
     // We can't practically devise classes for each of the many
     // intermediate steps of our custom transition
}

function indicateSuccessOrFail (element, successColor, failureColor) {
     var beginColor = element.style.backgroundColor;
     var ajaxSuccessCallback = function () {
         doFunkyTransition(element, beginColor, successColor);
     };
     var ajaxFailCallback = function () {
         doFunkyTransition(element, beginColor, failureColor);
     };
     someAjaxRequestFunction(ajaxSuccessCallback, ajaxFailCallback);
}


>>>> Or, for canvas specifically. You draw an animated "Hello" and want the
>>>> designer to be able to choose the fill color. You want to be able to
>>>> query the stylesheet easily to get the styling info.
>>>
>>> Or just set a class on your canvas and let styles apply to it as 
>>> normal?
>>
>> Maybe you are thinking of SVG here?
>
> No, I'm not.  Per the canvas spec, if I read it right, doing this:
>
>   myCanvas.className = "somethingStyled";
>   myCanvas.fillStyle = "currentColor";
>
> should set the fill style to the computed value of "color" on myCanvas 
> (and in particular, to whatever that computed value is given the class 
> "somethingStyled").  As it happens, Gecko doesn't implement this yet, 
> but the spec says to do it.  See 
> http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-canvas 
> paragraph starting "Whenever the CSS value currentColor".
Ok, I see, thank you for bringing that to my attention.
>
>> ..and even if one could, it would not be targeted to the specific shapes
>> needing styling.
>
> Canvas isn't retained-mode.  So you set your fill style, then draw the 
> shapes that need to have that style.  If you want a different style 
> for different shapes, you set the new fill style and draw those 
> shapes. There's no magic targeting involved...
Yes, I see per the example you gave that this would indeed work in the 
case of canvas (though only for colors).

thanks,
Brett

Received on Friday, 28 January 2011 01:01:40 UTC