jQuery: Получите высоту скрытого элемента в jQuery

Я должен получить высоту элемента, который является в отделении, которое скрыто. Прямо сейчас я показываю отделение, получаю высоту и скрываю родительское отделение. Это кажется немного глупым. Существует ли лучший путь?

Я использую jQuery 1.4.2:

$select.show();
optionHeight = $firstOption.height(); //we can only get height if its visible
$select.hide();
248
задан mkoryak 6 July 2012 в 10:29
поделиться

6 ответов

Вы можете сделать что-то вроде этого, хотя и немного взломать, забыв позицию , если она уже абсолютна:

var previousCss  = $("#myDiv").attr("style");

$("#myDiv").css({
    position:   'absolute', // Optional if #myDiv is already absolute
    visibility: 'hidden',
    display:    'block'
});

optionHeight = $("#myDiv").height();

$("#myDiv").attr("style", previousCss ? previousCss : "");
177
ответ дан 23 November 2019 в 03:00
поделиться

По определению, элемент имеет высоту, только если он видим.

Просто любопытно: зачем вам высота скрытого элемента?

Одна из альтернатив - эффективно скрыть элемент, поместив его позади (с помощью z-индекса) какого-либо наложения) .

1
ответ дан 23 November 2019 в 03:00
поделиться

Вы путаете два стиля CSS: стиль отображения и стиль видимости . .

Если элемент скрыт путем установки стиля css видимости, вы сможете получить высоту независимо от того, виден элемент или нет, поскольку элемент все еще занимает место на странице .

Если элемент скрыт путем изменения стиля отображения css на «none», то элемент не занимает места на странице, и вам придется задать ему стиль отображения, который приведет к тому, что элемент будет отображаться в некоторых пространство, в этот момент вы можете получить высоту.

39
ответ дан 23 November 2019 в 03:00
поделиться

Я действительно прибег к немного уловки, чтобы справиться с этим время от времени. Я разработал виджет полосы прокрутки jQuery, где я столкнулся с проблемой, о которой я не знаю заранее, является ли прокручиваемый контент частью скрытого фрагмента разметки или нет. Вот что я сделал:

// try to grab the height of the elem
if (this.element.height() > 0) {
    var scroller_height = this.element.height();
    var scroller_width = this.element.width();

// if height is zero, then we're dealing with a hidden element
} else {
    var copied_elem = this.element.clone()
                      .attr("id", false)
                      .css({visibility:"hidden", display:"block", 
                               position:"absolute"});
    $("body").append(copied_elem);
    var scroller_height = copied_elem.height();
    var scroller_width = copied_elem.width();
    copied_elem.remove();
}

По большей части это работает, но есть очевидная проблема, которая потенциально может возникнуть. Если контент, который вы клонируете, оформлен с помощью CSS, который включает ссылки на родительскую разметку в своих правилах, клонированное содержимое не будет содержать соответствующий стиль и, вероятно, будет иметь немного другие размеры. Чтобы обойти это, вы можете убедиться, что к клонируемой разметке применяются правила CSS, которые не включают ссылки на родительскую разметку.

Кроме того, это не подошло мне с моим виджетом скроллера, но чтобы получить подходящую высоту клонированного элемента, вам нужно установить ширину, равную ширине родительского элемента. В моем случае ширина CSS всегда применялась к фактическому элементу, поэтому мне не приходилось об этом беспокоиться, однако, если к элементу не применена ширина, вам может потребоваться выполнить какую-то рекурсивную обход предков DOM элемента, чтобы найти соответствующую ширину родительского элемента.

29
ответ дан 23 November 2019 в 03:00
поделиться

Вот сценарий, который я написал для обработки всех методов измерения jQuery для скрытых элементов, даже потомков скрытых родителей. Обратите внимание, что использование этого, конечно же, снижает производительность.

// Correctly calculate dimensions of hidden elements
(function($) {
    var originals = {},
        keys = [
            'width',
            'height',
            'innerWidth',
            'innerHeight',
            'outerWidth',
            'outerHeight',
            'offset',
            'scrollTop',
            'scrollLeft'
        ],
        isVisible = function(el) {
            el = $(el);
            el.data('hidden', []);

            var visible = true,
                parents = el.parents(),
                hiddenData = el.data('hidden');

            if(!el.is(':visible')) {
                visible = false;
                hiddenData[hiddenData.length] = el;
            }

            parents.each(function(i, parent) {
                parent = $(parent);
                if(!parent.is(':visible')) {
                    visible = false;
                    hiddenData[hiddenData.length] = parent;
                }
            });
            return visible;
        };

    $.each(keys, function(i, dimension) {
        originals[dimension] = $.fn[dimension];

        $.fn[dimension] = function(size) {
            var el = $(this[0]);

            if(
                (
                    size !== undefined &&
                    !(
                        (dimension == 'outerHeight' || 
                            dimension == 'outerWidth') &&
                        (size === true || size === false)
                    )
                ) ||
                isVisible(el)
            ) {
                return originals[dimension].call(this, size);
            }

            var hiddenData = el.data('hidden'),
                topHidden = hiddenData[hiddenData.length - 1],
                topHiddenClone = topHidden.clone(true),
                topHiddenDescendants = topHidden.find('*').andSelf(),
                topHiddenCloneDescendants = topHiddenClone.find('*').andSelf(),
                elIndex = topHiddenDescendants.index(el[0]),
                clone = topHiddenCloneDescendants[elIndex],
                ret;

            $.each(hiddenData, function(i, hidden) {
                var index = topHiddenDescendants.index(hidden);
                $(topHiddenCloneDescendants[index]).show();
            });
            topHidden.before(topHiddenClone);

            if(dimension == 'outerHeight' || dimension == 'outerWidth') {
                ret = $(clone)[dimension](size ? true : false);
            } else {
                ret = $(clone)[dimension]();
            }

            topHiddenClone.remove();
            return ret;
        };
    });
})(jQuery);
0
ответ дан 23 November 2019 в 03:00
поделиться

Вы также можете расположить скрытый div за пределами экрана с отрицательным полем вместо использования display: none, что очень похоже на технику замены изображения с отступом текста.

например.

position:absolute;
left:  -2000px;
top: 0;

Таким образом, высота () все еще доступна.

4
ответ дан 23 November 2019 в 03:00
поделиться