jQuery-получить ширину элемента, когда он не виден (дисплей: нет)



похоже, что в jQuery, когда элемент не виден width() возвращает 0. Имеет смысл, но мне нужно сделать ширину таблицы, чтобы установить ширину родителя, прежде чем я покажу родителя.



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



<div id="parent">
Text here ... Can get very long and skew the parent
<table> ... </table>
Text here too ... which is why I want to shrink the parent based on the table
</div>


CSS:



#parent
{
display: none;
}


Javascript:



var tableWidth = $('#parent').children('table').outerWidth();
if (tableWidth > $('#parent').width())
{
$('#parent').width(tableWidth);
}


tableWidth всегда возвращает 0, так как он не виден (это мое предположение, так как он дает мне номер, когда он виден). Есть ли способ получить ширину таблицы, не делая видимым родителя?

756   11  

11 ответов:

вот трюк, который я использовал. Это включает в себя добавление некоторых свойств CSS, чтобы заставить jQuery думать, что элемент виден, но на самом деле он все еще скрыт.

var $table = $("#parent").children("table");
$table.css({ position: "absolute", visibility: "hidden", display: "block" });
var tableWidth = $table.outerWidth();
$table.css({ position: "", visibility: "", display: "" });

Это своего рода хак, но он, кажется, работает хорошо для меня.

обновление

С тех пор я написал a блоге, который охватывает эту тему. Метод, используемый выше, может быть проблематичным, так как вы сбрасываете свойства CSS на пустые значения. А что если раньше у них были ценности? Обновленное решение использует метод swap (), который был найден в исходном коде jQuery.

код из ссылки блог:

//Optional parameter includeMargin is used when calculating outer dimensions  
(function ($) {
$.fn.getHiddenDimensions = function (includeMargin) {
    var $item = this,
    props = { position: 'absolute', visibility: 'hidden', display: 'block' },
    dim = { width: 0, height: 0, innerWidth: 0, innerHeight: 0, outerWidth: 0, outerHeight: 0 },
    $hiddenParents = $item.parents().andSelf().not(':visible'),
    includeMargin = (includeMargin == null) ? false : includeMargin;

    var oldProps = [];
    $hiddenParents.each(function () {
        var old = {};

        for (var name in props) {
            old[name] = this.style[name];
            this.style[name] = props[name];
        }

        oldProps.push(old);
    });

    dim.width = $item.width();
    dim.outerWidth = $item.outerWidth(includeMargin);
    dim.innerWidth = $item.innerWidth();
    dim.height = $item.height();
    dim.innerHeight = $item.innerHeight();
    dim.outerHeight = $item.outerHeight(includeMargin);

    $hiddenParents.each(function (i) {
        var old = oldProps[i];
        for (var name in props) {
            this.style[name] = old[name];
        }
    });

    return dim;
}
}(jQuery));
function realWidth(obj){
    var clone = obj.clone();
    clone.css("visibility","hidden");
    $('body').append(clone);
    var width = clone.outerWidth();
    clone.remove();
    return width;
}
realWidth($("#parent").find("table:first"));

основываясь на ответе Робертса, вот моя функция. Это работает для меня, если элемент или его родитель были исчезли через jQuery, может либо получить внутренние или внешние размеры, а также возвращает значения смещения.

/edit1: переписал функцию. теперь он меньше и может быть вызван непосредственно на объект

/ edit2: теперь функция будет вставлять клон сразу после исходного элемента вместо тела, что позволяет клону поддерживать унаследованный размеры.

$.fn.getRealDimensions = function (outer) {
    var $this = $(this);
    if ($this.length == 0) {
        return false;
    }
    var $clone = $this.clone()
        .show()
        .css('visibility','hidden')
        .insertAfter($this);        
    var result = {
        width:      (outer) ? $clone.outerWidth() : $clone.innerWidth(), 
        height:     (outer) ? $clone.outerHeight() : $clone.innerHeight(), 
        offsetTop:  $clone.offset().top, 
        offsetLeft: $clone.offset().left
    };
    $clone.remove();
    return result;
}

var dimensions = $('.hidden').getRealDimensions();

Спасибо за публикацию функции realWidth выше, это действительно помогло мне. Основываясь на функции" realWidth " выше, я написал, сброс CSS, (причина описана ниже).

function getUnvisibleDimensions(obj) {
    if ($(obj).length == 0) {
        return false;
    }

    var clone = obj.clone();
    clone.css({
        visibility:'hidden',
        width : '',
        height: '',
        maxWidth : '',
        maxHeight: ''
    });
    $('body').append(clone);
    var width = clone.outerWidth(),
        height = clone.outerHeight();
    clone.remove();
    return {w:width, h:height};
}

"realWidth" получает ширину существующего тега. Я проверил это с некоторыми тегами изображений. Проблема была в том, что когда изображение дало размер CSS на ширину (или максимальную ширину), вы никогда не получите реальный размер этого изображения. Возможно, у img есть " max-width: 100%", функция "realWidth" клонирует его и добавляет его к телу. Если исходный размер изображения больше, чем тело, то вы получаете размер тела, а не реальный размер этого изображения.

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

пример flexibox enter image description here

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

к сожалению, JavaScript не предоставляет никаких прямых событий для уведомления, когда элемент отображается или скрыт. Однако я создаю некоторую функцию на основе измененного API атрибута DOM, которая будет выполнять функцию обратного вызова при изменении видимости элемента.

$('[selector]').onVisibleChanged(function(e, isVisible)
{
    var realWidth = $('[selector]').width();
    var realHeight = $('[selector]').height();

    // render or adjust something
});

для получения дополнительной информации, пожалуйста, посетите мой проект GitHub.

https://github.com/Soul-Master/visible.event.js

демо: http://jsbin.com/ETiGIre/7

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

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

пример:

$itemClone = $('.hidden-item').clone().css({
        'visibility': 'hidden',
        'position': 'absolute',
        'z-index': '-99999',
        'left': '99999999px',
        'top': '0px'
    }).appendTo('body');
var width = $itemClone.width();
$itemClone.remove();

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

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

например:

$(img).css("opacity", 0)  //element cannot be seen
width = $(img).width()    //but has width

перед тем, как взять ширину сделать Родительский дисплей показать, а затем взять ширину и, наконец, сделать Родительский дисплей скрыть. Так же, как после

$('#parent').show();
var tableWidth = $('#parent').children('table').outerWidth();
 $('#parent').hide();
if (tableWidth > $('#parent').width())
{
    $('#parent').width() = tableWidth;
}

самая большая проблема, пропущенная большинством решений здесь, заключается в том, что ширина элемента часто изменяется CSS на основе того, где он ограничен в html.

Если бы я должен был определить offsetWidth элемента, добавив его клон к телу, когда у него есть стили, которые применяются только в его текущей области, я бы получил неправильную ширину.

например:

/ / css

.модуль-контейнер. my-elem{ границы: 60px сплошной черный; }

теперь, когда я попробовать чтобы определить ширину my-elem в контексте тела, она будет равна 120px. Вместо этого вы можете клонировать контейнер модуля, но ваш JS не должен знать эти детали.

Я не тестировал его, но по существу решение Soul_Master, похоже, является единственным, которое может работать должным образом. Но, к сожалению, глядя на реализацию, она, вероятно, будет дорогостоящей в использовании и плохой для производительности (как и большинство представленных здесь решений.)

Если это вообще возможно то используйте видимость: скрытый вместо этого. Это по-прежнему будет отображать элемент, что позволяет рассчитать ширину без всякой суеты.

кроме ответ, опубликованный Тимом Бэнксом, что последовало за решением моей проблемы, мне пришлось отредактировать одну простую вещь.

У кого-то еще может быть такая же проблема; я работаю с раскрывающимся списком Bootstrap в раскрывающемся списке. Но текст может быть шире, чем текущий контент на данный момент (и не так много хороших способов решить это с помощью css).

Я:

$table.css({ position: "absolute", visibility: "hidden", display: "table" });

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

jQuery(".megamenu li.level0 .dropdown-container .sub-column ul .level1").on("mouseover", function () {
    var sum = 0;
    jQuery(this).find('ul li.level2').each(function(){
    sum -= jQuery(this).height();
    jQuery(this).parent('ul').css('margin-top', sum / 1.8);
    console.log(sum);
    });
});

при наведении курсора мы можем вычислить высоту элемента списка.

Comments

    Ничего не найдено.