Подтвердить что ты не робот

Правила CSS с несколькими возможными значениями (jQuery)

Вопрос прост; используя функцию 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 лучше, я предлагаю прочитать об этом. Вопрос старается сосредоточиться на более обобщенном вопросе. Например, он также может применяться к этому 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 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;
}

Спасибо, всем, за ваши материалы.

4b9b3361

Ответ 1

Я не думаю, что любой браузер, или W3C, обеспечивает хороший способ сделать это.

Усложняющим фактором является знание того, какие стили отменяют предыдущие стили (например, подчеркивание или отсутствие подчеркивания).

Итак, нам понадобится несколько поисковых таблиц или человеческих суждений, чтобы узнать, какой стиль действительно применяется.

Наконец, все эти методы (до сих пор три ответа) не могут различать пустую или отсутствующую настройку стиля и явно установленный 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') );


Посмотрите на действие в jsFiddle.

Результаты:

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

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

Ответ 2

Здесь возможно решение:

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/

Ответ 3

Хорошо, это не простой, элегантный ответ, который вы ищете, но у меня есть рабочий вариант здесь: http://jsfiddle.net/nrabinowitz/Uu6p3/1/

Он похож на @Thor по понятию, но использует встроенные функции 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.

Ответ 4

Если вы попытаетесь установить внутренний диапазон на text-decoration:none, вы заметите, что подчеркивание по-прежнему отображается из родительского div. Проблема в том, что text-decoration не наследует, но выглядит так, как будто это делает.

Таким образом, любой текстовый элемент будет отображать комбинацию всех текстовых украшений его родителей, даже если у этого или любого из его родителей есть текстовое украшение, которое не имеет значения.

Если вы хотите знать все текстовые украшения, которые были применены к тексту, вам нужно пройти цепочку прямо вверх и записать комбинацию всех украшений, с которыми вы сталкиваетесь, за исключением "none". Вот пример:

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