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, поскольку он не отображается (это мое предположение, поскольку оно дает мне число, когда оно видимо). Есть ли способ получить ширину таблицы без видимости родителя?
Ответы
Ответ 1
Вот трюк, который я использовал. Это связано с добавлением некоторых свойств CSS, чтобы jQuery считал элемент видимым, но на самом деле он по-прежнему скрыт.
var $table = $("#parent").children("table");
$table.css({ position: "absolute", visibility: "hidden", display: "block" });
var tableWidth = $table.outerWidth();
$table.css({ position: "", visibility: "", display: "" });
Это своего рода взлом, но, похоже, он отлично работает для меня.
ОБНОВИТЬ
С тех пор я написал сообщение в блоге, которое охватывает эту тему. Метод, использованный выше, потенциально может быть проблематичным, поскольку вы возвращаете свойства 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));
Ответ 2
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"));
Ответ 3
На основе ответа Робертса, вот моя функция.
Это работает для меня, если элемент или его родительский элемент исчезли через 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();
Ответ 4
Благодарим вас за отправку функции realWidth выше, это действительно помогло мне.
Основанный на функции "realWidth" выше, я написал CSS reset (причина, описанная ниже).
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" клонирует его и добавляет в тело.
Если исходный размер изображения больше, чем тело, то вы получаете размер тела, а не реальный размер этого изображения.
Ответ 5
Я пытаюсь найти рабочую функцию для скрытого элемента, но я понимаю, что CSS очень сложный, чем все думают. В CSS3 есть много новых методов компоновки, которые могут не работать для всех предыдущих ответов, таких как гибкий ящик, сетка, столбец или четный элемент внутри сложного родительского элемента.
пример flexibox
![enter image description here]()
Я думаю, что единственным устойчивым и простым решением является рендеринг в реальном времени. В то время браузер должен предоставить вам правильный размер элемента.
К сожалению, JavaScript не предоставляет никакого прямого события для уведомления, когда элемент отображается или скрыт. Тем не менее, я создаю некоторую функцию, основанную на DOM Attribute Modified API, которая будет выполнять функцию обратного вызова при изменении видимости элемента.
$('[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
demo: http://jsbin.com/ETiGIre/7
Ответ 6
Если вам нужна ширина того, что скрыто, и вы не можете скрыть его по какой-либо причине, вы можете клонировать его, изменять 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();
Ответ 7
Перед тем, как принять ширину, отобразите родительский экран, затем возьмите ширину и, наконец, скройте родительский экран. Как и после
$('#parent').show();
var tableWidth = $('#parent').children('table').outerWidth();
$('#parent').hide();
if (tableWidth > $('#parent').width())
{
$('#parent').width() = tableWidth;
}
Ответ 8
Одно из решений, хотя оно не будет работать во всех ситуациях, должно скрыть элемент, установив непрозрачность на 0. Полностью прозрачный элемент будет иметь ширину.
Откат состоит в том, что элемент все равно будет занимать место, но это не будет проблемой во всех случаях.
Например:
$(img).css("opacity", 0) //element cannot be seen
width = $(img).width() //but has width
Ответ 9
Самая большая проблема, с которой приходится сталкиваться большинством решений, заключается в том, что ширина элемента часто изменяется с помощью CSS на основе того, где он ограничен в html.
Если бы я должен был определять offsetWidth элемента, добавив клон его в тело, когда он имеет стили, которые применяются только в его текущей области, я бы получил неправильную ширину.
например:
//CSS
.module-container.my-elem { граница: 60px сплошная черная;
}
теперь, когда я пытаюсь определить ширину my-elem в контексте тела, он будет отсутствовать на 120 пикселей. Вместо этого вы можете клонировать контейнер модуля, но ваш JS не должен знать эти данные.
Я не тестировал его, но, по сути, решение Soul_Master оказалось единственным, которое могло бы работать должным образом. Но, к сожалению, глядя на реализацию, это, вероятно, будет дорогостоящим для использования и плохим для производительности (как и большинство представленных здесь решений).
Если это вообще возможно, используйте видимость: скрытый. Это все равно будет отображать элемент, позволяя вам рассчитать ширину без всякой суеты.
Ответ 10
В дополнение к ответу, опубликованному Тимом Бэнксом, который последовал за решением моей проблемы, мне пришлось отредактировать одну простую вещь.
У кого-то другого может быть такая же проблема; Я работаю с выпадающим списком Bootstrap в раскрывающемся меню. Но текст может быть шире как текущее содержимое на этом этапе (и не так много хороших способов решить это через css).
Я использовал:
$table.css({ position: "absolute", visibility: "hidden", display: "table" });
который устанавливает контейнер в таблицу, которая всегда масштабируется по ширине, если содержимое более широкое.
Ответ 11
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);
});
});
При наведении мы можем вычислить высоту элемента списка.
Ответ 12
Как было сказано ранее, метод клонирования и присоединения в другом месте не гарантирует такие же результаты, так как стилизация может отличаться.
Ниже мой подход. Он перемещается вверх по родителям в поисках родителя, ответственного за сокрытие, а затем временно показывает его, чтобы вычислить необходимую ширину, высоту и т.д.
var width = parseInt($image.width(), 10);
var height = parseInt($image.height(), 10);
if (width === 0) {
if ($image.css("display") === "none") {
$image.css("display", "block");
width = parseInt($image.width(), 10);
height = parseInt($image.height(), 10);
$image.css("display", "none");
}
else {
$image.parents().each(function () {
var $parent = $(this);
if ($parent.css("display") === "none") {
$parent.css("display", "block");
width = parseInt($image.width(), 10);
height = parseInt($image.height(), 10);
$parent.css("display", "none");
}
});
}
}