具有多个可能值的CSS规则(jQuery)

时间:2022-10-25 08:38:23

The question is simple; using jQuery's css function, the computed style of a CSS attribute may be returned, but what if there are more than one style for that attribute being rendered? For example :

问题很简单;使用jQuery的css函数,可以返回CSS属性的计算样式,但是如果要呈现的属性有多个样式呢?例如 :

<div id="foo" style="text-decoration:underline;">Some underline text</div>

The instruction $('#foo').css('text-decoration'); will return underline. Now if I change it to

指令$('#foo')。css('text-decoration');将返回下划线。现在如果我改成它

<div id="foo" style="text-decoration:underline;">Some underline <span id="bar" style="text-decoration:line-through;">text</span></div>

The instruction $('#bar').css('text-decoration'); will return line-through, alright.

指令$('#bar')。css('text-decoration');将返回直通,好吧。

But the actual text is also underline! How can I return both? Do I need to search all ancestors if I want to know if some text is both underline and line-through? Sounds a bit painful, no?

但实际的文字也强调了!我怎么能两个回来?如果我想知道某些文本是否都是下划线和直通,我是否需要搜索所有祖先?听起来有点痛苦,不是吗?

** Edit **

**编辑**

Another problem arises whith this HTML

这个HTML出现了另一个问题

<span style="text-decoration:underline;">some <span id="e1" style="font-weight:bold;">text</span></span>

where $('#e1').css('text-decoration'); returns none for some reason, while the text is clearly rendered with an underline.

其中$('#e1')。css('text-decoration');由于某种原因返回none,而文本清楚地使用下划线呈现。

** Disclaimer **

**免责声明**

This question is not to debate how the UA renders an element, but if an element hierarchy applies a CSS or not. If one wants to understand text-decoration better, I suggest one would read about it. The question tries to focus on a more generalize matter. For example, it can also apply to this HTML

这个问题不是讨论UA如何呈现元素,而是元素层次结构是否应用了CSS。如果想要更好地理解文本装饰,我建议人们阅读它。这个问题试图关注更广泛的问题。例如,它也可以应用于此HTML

<div style="display:none;">Some <span id="keyword" style="text-decoration:underline;">hidden</span> text</div>

where one could want to know if the element keyword is visible or not. With the code below, this is simply done with

人们可能想知道元素关键字是否可见。使用下面的代码,只需完成

cssLookup($('#keyword'), 'display', 'none');   // -> true

** UPDATE **

**更新**

After all the answers and comments, here is, based on Brock Adams solution :

在完成所有答案和评论后,基于Brock Adams解决方案:

/**
 * Lookup the given node and node's parents for the given style value. Returns boolean
 *
 * @param e     element (jQuery object)
 * @param style the style name
 * @param value the value to look for
 * @return boolean
 */  
function cssLookup(e, style, value) {
    var result = (e.css(style) == value);
    if (!result) {
        e.parents().each(function() {
            if ($(this).css(style) == value) {
                result = true;
                return false;
            }
        });
    }

    return result;
}

Thank you, everyone, for your inputs.

谢谢大家的意见。

4 个解决方案

#1


2  

I don't think any browser, or the W3C, provides a good way to do this.

我认为任何浏览器或W3C都不提供这样做的好方法。

A complicating factor is knowing which styles cancel preceding styles (underline versus no-underline, for example).

一个复杂的因素是知道哪些样式取消了先前的样式(例如,下划线与非下划线)。

So, we would need multiple look-up tables or human judgement to know which style actually applied.

因此,我们需要多个查找表或人工判断来了解实际应用的样式。

Finally, all these methods (3 answers so far) cannot distinguish between a blank, or missing, style setting and an explicitly set none. Obviously the browser can render an explicitly set none differently than a blank or missing setting.

最后,所有这些方法(到目前为止3个答案)无法区分空白或缺失的样式设置和明确设置的无。显然,浏览器可以呈现显式设置,与空白或缺少设置无异。

For human use, this code should do the trick:

对于人类使用,此代码应该可以解决问题:

function cssTree (jNode, styleName, bShowBlanks) {
    var styleArray  = [jNode.css (styleName)];

    jNode.parents ().map ( function () {
        var style   = $(this).css (styleName);

        if (bShowBlanks  ||  ! /^(none|\s*)$/i.test (style) )
            styleArray.push (style);
    } );
    return styleArray;
}

alert ( cssTree ( $("#bar"), 'text-decoration') );


See it in action at jsFiddle.

在jsFiddle看到它的行动。

Results:

bar: line-through,underline
el: none,underline

//-- With bShowBlanks = true.
bar: line-through,underline,none,none
el: none,underline,none,none

#2


1  

Ok, this is not the easy, elegant answer you're looking for, but I have a working option here: http://jsfiddle.net/nrabinowitz/Uu6p3/1/

好的,这不是你想要的简单,优雅的答案,但我有一个工作选择:http://jsfiddle.net/nrabinowitz/Uu6p3/1/

It's similar to @Thor's in concept, but uses built-in jQuery functions to find all ancestors, map their text-decoration styles into an array, filter for unique values not equal to "none", and return the array of styles:

它类似于@Tor的概念,但使用内置的jQuery函数来查找所有祖先,将其文本修饰样式映射到数组中,过滤不等于“none”的唯一值,并返回样式数组:

/**
 * Generic function to find all values for
 * CSS settings that allow multiple values.
 *
 * @param {String} selector    JQuery selector
 * @param {String} attr        CSS attribute to look for
 * @param {String[]} ignore    Values to ignore
 */
function findAllCssValues(selector, attr, ignore) {
    var temp = {};
    ignore = ignore || ['none'];
    return $.grep(
        // create the array of all values
        $(selector)
            // select element and all ancestors
            .parents().andSelf()
            // put all css attribute results into an array
            .map(function() {
                return $(this).css(attr)
            })
            // make it a regular Javascript array
            .toArray(),
        // now filter for unique values that aren't "none"
        function(val) {
            if (val in temp || $.inArray(val, ignore) >= 0) {
                return false;
            }
            temp[val] = true;
            return true;
        }
    );
}

findAllCssValues('#bar', 'text-decoration');

It works for all of your example snippets, as shown in the fiddle. I made it work for any CSS property, though I'm not sure this issue applies to anything but text-decoration.

它适用于所有示例代码段,如小提琴中所示。我使它适用于任何CSS属性,但我不确定这个问题是否适用于除文本修饰之外的任何内容。

#3


1  

Here's a possible solution:

这是一个可能的解决方案:

function getVisualCSS(tag, elem){
    var styles = [];
    var thisStyle = $(elem).css(tag);
    if(thisStyle != 'none') styles.push(thisStyle);
    while($(elem).parent()[0].tagName != 'BODY'){
        styles.push($(elem).parent().css(tag));
        elem = $(elem).parent();
    }
    styles.push($(elem).parent().css(tag));
    return $.unique($.grep(styles, function(n){
        return n != 'none';
    }));  
}

What it does is, that it checks all of an elements ancestors for a given CSS tag.

它的作用是,它检查给定CSS标记的所有元素祖先。

For the sake of an "cleaner" array, all none values are removed and only unique values are returned.

为了“清理”数组,不删除所有值,只返回唯一值。

Here's a fiddle: http://jsfiddle.net/nslr/bXx46/2/

这是一个小提琴:http://jsfiddle.net/nslr/bXx46/2/

#4


-1  

If you try to set the inner span to text-decoration:none you'll notice the underline is still rendered from the parent div. The issue is that text-decoration doesn't inherit, but it's rendered as if it does.

如果您尝试将内部跨度设置为text-decoration:none,您将注意到仍然从父div渲染下划线。问题是文本修饰不会继承,但它会像它一样呈现。

So any text element will render the combination of all of its parents' text-decorations, even if it or any of its parents have text-decoration set to none.

因此,任何文本元素都将呈现其所有父项的文本装饰的组合,即使它或其任何父项的文本装饰设置为无。

If you want to know all of the text-decorations that have been applied to the text, you need to walk the chain right up to the top and record the combination of all decorations you encounter, excluding "none". Here's an example:

如果您想知道已应用于文本的所有文本装饰,您需要将链条一直走到顶部并记录您遇到的所有装饰的组合,不包括“无”。这是一个例子:

http://jsfiddle.net/fSESn/4/

function findDecoration( elem ) {
    var $elem = $(elem);
    var found = new Array();
    var dec = "";

    var current = $elem.css('text-decoration');

    if ( current != 'none' ) {
        found[ current ] = 1;
        dec = current;
    }

    var p = $elem.parent();
    while ( p != null && p.get(0).nodeName.toLowerCase() != 'body' ) {
        current = p.css('text-decoration');

        if ( current != 'none' && found[ current ] == null ) {
            found[ current ] = 1;
            dec = current + " " + dec;
        }
        p = p.parent();
    }

    return dec;
}

#1


2  

I don't think any browser, or the W3C, provides a good way to do this.

我认为任何浏览器或W3C都不提供这样做的好方法。

A complicating factor is knowing which styles cancel preceding styles (underline versus no-underline, for example).

一个复杂的因素是知道哪些样式取消了先前的样式(例如,下划线与非下划线)。

So, we would need multiple look-up tables or human judgement to know which style actually applied.

因此,我们需要多个查找表或人工判断来了解实际应用的样式。

Finally, all these methods (3 answers so far) cannot distinguish between a blank, or missing, style setting and an explicitly set none. Obviously the browser can render an explicitly set none differently than a blank or missing setting.

最后,所有这些方法(到目前为止3个答案)无法区分空白或缺失的样式设置和明确设置的无。显然,浏览器可以呈现显式设置,与空白或缺少设置无异。

For human use, this code should do the trick:

对于人类使用,此代码应该可以解决问题:

function cssTree (jNode, styleName, bShowBlanks) {
    var styleArray  = [jNode.css (styleName)];

    jNode.parents ().map ( function () {
        var style   = $(this).css (styleName);

        if (bShowBlanks  ||  ! /^(none|\s*)$/i.test (style) )
            styleArray.push (style);
    } );
    return styleArray;
}

alert ( cssTree ( $("#bar"), 'text-decoration') );


See it in action at jsFiddle.

在jsFiddle看到它的行动。

Results:

bar: line-through,underline
el: none,underline

//-- With bShowBlanks = true.
bar: line-through,underline,none,none
el: none,underline,none,none

#2


1  

Ok, this is not the easy, elegant answer you're looking for, but I have a working option here: http://jsfiddle.net/nrabinowitz/Uu6p3/1/

好的,这不是你想要的简单,优雅的答案,但我有一个工作选择:http://jsfiddle.net/nrabinowitz/Uu6p3/1/

It's similar to @Thor's in concept, but uses built-in jQuery functions to find all ancestors, map their text-decoration styles into an array, filter for unique values not equal to "none", and return the array of styles:

它类似于@Tor的概念,但使用内置的jQuery函数来查找所有祖先,将其文本修饰样式映射到数组中,过滤不等于“none”的唯一值,并返回样式数组:

/**
 * Generic function to find all values for
 * CSS settings that allow multiple values.
 *
 * @param {String} selector    JQuery selector
 * @param {String} attr        CSS attribute to look for
 * @param {String[]} ignore    Values to ignore
 */
function findAllCssValues(selector, attr, ignore) {
    var temp = {};
    ignore = ignore || ['none'];
    return $.grep(
        // create the array of all values
        $(selector)
            // select element and all ancestors
            .parents().andSelf()
            // put all css attribute results into an array
            .map(function() {
                return $(this).css(attr)
            })
            // make it a regular Javascript array
            .toArray(),
        // now filter for unique values that aren't "none"
        function(val) {
            if (val in temp || $.inArray(val, ignore) >= 0) {
                return false;
            }
            temp[val] = true;
            return true;
        }
    );
}

findAllCssValues('#bar', 'text-decoration');

It works for all of your example snippets, as shown in the fiddle. I made it work for any CSS property, though I'm not sure this issue applies to anything but text-decoration.

它适用于所有示例代码段,如小提琴中所示。我使它适用于任何CSS属性,但我不确定这个问题是否适用于除文本修饰之外的任何内容。

#3


1  

Here's a possible solution:

这是一个可能的解决方案:

function getVisualCSS(tag, elem){
    var styles = [];
    var thisStyle = $(elem).css(tag);
    if(thisStyle != 'none') styles.push(thisStyle);
    while($(elem).parent()[0].tagName != 'BODY'){
        styles.push($(elem).parent().css(tag));
        elem = $(elem).parent();
    }
    styles.push($(elem).parent().css(tag));
    return $.unique($.grep(styles, function(n){
        return n != 'none';
    }));  
}

What it does is, that it checks all of an elements ancestors for a given CSS tag.

它的作用是,它检查给定CSS标记的所有元素祖先。

For the sake of an "cleaner" array, all none values are removed and only unique values are returned.

为了“清理”数组,不删除所有值,只返回唯一值。

Here's a fiddle: http://jsfiddle.net/nslr/bXx46/2/

这是一个小提琴:http://jsfiddle.net/nslr/bXx46/2/

#4


-1  

If you try to set the inner span to text-decoration:none you'll notice the underline is still rendered from the parent div. The issue is that text-decoration doesn't inherit, but it's rendered as if it does.

如果您尝试将内部跨度设置为text-decoration:none,您将注意到仍然从父div渲染下划线。问题是文本修饰不会继承,但它会像它一样呈现。

So any text element will render the combination of all of its parents' text-decorations, even if it or any of its parents have text-decoration set to none.

因此,任何文本元素都将呈现其所有父项的文本装饰的组合,即使它或其任何父项的文本装饰设置为无。

If you want to know all of the text-decorations that have been applied to the text, you need to walk the chain right up to the top and record the combination of all decorations you encounter, excluding "none". Here's an example:

如果您想知道已应用于文本的所有文本装饰,您需要将链条一直走到顶部并记录您遇到的所有装饰的组合,不包括“无”。这是一个例子:

http://jsfiddle.net/fSESn/4/

function findDecoration( elem ) {
    var $elem = $(elem);
    var found = new Array();
    var dec = "";

    var current = $elem.css('text-decoration');

    if ( current != 'none' ) {
        found[ current ] = 1;
        dec = current;
    }

    var p = $elem.parent();
    while ( p != null && p.get(0).nodeName.toLowerCase() != 'body' ) {
        current = p.css('text-decoration');

        if ( current != 'none' && found[ current ] == null ) {
            found[ current ] = 1;
            dec = current + " " + dec;
        }
        p = p.parent();
    }

    return dec;
}