JQuery: почему .width() иногда возвращает 0 после вставки элементов с .html()?
Я получаю некоторый html и вставляю его с .html()
, после чего я пытаюсь получить ширину одного из вновь вставленных элементов с .width()
(который имеет правило CSS). Однако иногда - ширина не поднимается и возвращается как 0.
Это потому, что JS запускает "впереди" вновь созданных элементов и их css? Я пробовал цепочку с .html('...').find('...').width()
, но она по-прежнему иногда не работает. Какая причина и есть ли работа?
Изменить: По популярному запросу, ПРИМЕР:
/* ajax.response is:
<div class="boxes">
<div class="box width-A">test 1</div>
<div class="box width-B">test 2</div>
<div class="box width-C">test 3</div>
</div> */
var boxOutput = $('.boxOutput'); /* .boxOutput is already on the page */
boxOutput.html(ajax.response);
// make width of ".boxes" equal to the sum of all ".box"
var boxWidth = 0;
$('.box', boxOutput).each(function(i) {
boxWidth += $(this).width(); /* this is where sometimes width returns 0 */
});
$('.boxes', boxOutput).css('width', boxWidth);
Мой исходный код слишком длинный/уродливый для копирования/вставки, но это упрощенная точная вещь, которую я делаю (извините, если там какая-то глупая ошибка, слишком поздно, когда я: P). Получив html обратно из ajax, поместив его в div, я хочу получить ширину каждого окна (потому что он может быть другим), а затем использовать эту ширину. Опять же, 90% времени, ширина возвращается правильно. Это те 10%, когда иногда ширина равна 0: (
Ответы
Ответ 1
Зависит от того, какой браузер. Иногда я нахожу, что что-то сломается с синхронными ожиданиями рендеринга времени выполнения javascript, и мне нужно будет получить результат на следующем тике.
Я бы попробовал:
$(elem).html(data);
setTimeout(function(){
// Get the width here
},0);
Ответ 2
jQuery вернет нулевую ширину, если элемент не отображается. Например, у меня была такая же проблема, когда элемент был вставлен на вкладку скрытой формы. Временно назначив его телу, где он был виден, я смог определить ширину:
$("body").append(el); // First assign it to the body so that it visible
var width = el.width(); // The width will now be correct
wrapper.append(el); // Now place the element where you want it.
Одно из предостережений заключается в том, что если элемент наследует разные стили при назначении телу, тогда ширина может быть неправильной.
Ответ 3
Не уверен 100%, но я думаю, что ваша проблема в том, что код, вызываемый вне функции, в которую вы прикрепляете элементы, не распознает вновь созданные элементы. Быстрый пример:
<div id="container">
</div>
<script>
$(document).ready(function() {
$('#container).html('<p style="width:200px">Lorem ipsum</p>');
alert($('#container p').width()); // alerts 0
$('#container p').html('Lorem ipsum dolor sit amet'); // if content doesn't change, it clearly a problem of jquery not being able to bind the functions to your new elements
});
</script>
Если вы можете сказать нам, что вы делаете, мы обязательно найдем решение.
LATER EDIT
Теперь, когда вы разместили код, я действительно могу помочь. Вам нужно запустить этот код:
$('.box', boxOutput).each(function(i) {
boxWidth += $(this).width(); /* this is where sometimes width returns 0 */
});
в функции в вашей функции ответа ajax. Пример:
$.get('script.php', function(data) {
$('#elem').html(data);
// your code for width()
});
Надеюсь, что это поможет.
Ответ 4
Мы выяснили, что document.ready был недостаточно хорош, поэтому 300ms работало хорошо:
setTimeout(function() {
resizeHeightOfMyDiv();
$(window).on("resize", function() {
resizeHeightOfMyDiv();
});
}, 300);
Ответ 5
// ...
$('.box', boxOutput).each(function(i) {
//boxWidth += $(this).width(); /* this is where sometimes width returns 0 */
boxWidth += this..getBoundingClientRect().width;
});
//...