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

时间:2011-07-14 04:23:47

标签: javascript jquery css

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

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

指令$('#foo').css('text-decoration');将返回underline。现在,如果我将其更改为

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

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

但实际文字也是 underline!我怎么能两个都回来?如果我想知道某些文字是underline还是line-through,我是否需要搜索所有祖先?听起来有点痛苦,不是吗?

** 修改 **

这个HTML出现了另一个问题

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

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

** 免责声明 **

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

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

在哪里可以想知道元素keyword是否可见。使用下面的代码,只需使用

即可完成
cssLookup($('#keyword'), 'display', 'none');   // -> true

** 更新 **

在完成所有答案和评论之后,基于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;
}

谢谢大家的意见。

4 个答案:

答案 0 :(得分:2)

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

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

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

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

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

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.

<强>结果:

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

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

答案 1 :(得分:1)

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

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';
    }));  
}

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

为了“清理”数组,将删除所有none值,并仅返回唯一值。

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

答案 2 :(得分:1)

好的,这不是您正在寻找的简单,优雅的答案,但我在这里有一个工作选项:http://jsfiddle.net/nrabinowitz/Uu6p3/1/

它与概念中的@Tir相似,但使用内置的jQuery函数来查找所有祖先,将其text-decoration样式映射到数组中,过滤不等于"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');

它适用于所有示例代码段,如小提琴中所示。我使它适用于任何CSS属性,但我不确定此问题是否适用于text-decoration以外的任何内容。

答案 3 :(得分:-1)

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

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

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

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;
}