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

Получить фактическую ширину и высоту компонента

Мы сталкиваемся с довольно страшной проблемой в JavaScript, которую никто из нас, похоже, не может решить:

Как мы можем получить ширину и высоту элемента DOM, включая дочерние элементы, всю модель коробки и т.д. без отображения компонента на странице?

Помните: я ищу предложения. Даже ответы, которые полностью не отвечают на вопрос (или не совсем соответствуют указанным параметрам), могут и, возможно, будут полезны.

Основная цель: Я добавляю HTML-элементы на страницу через Javascript - HTML-элементы с размерами и стилями из базы данных. Проблема в том, что они плохо себя ведут, как правило, плохой алимент, один элемент больше, чем другой из-за заполнения/поля, и поэтому мне нужно проверить их фактический размер, чтобы исправить эти проблемы.

Результирующее приложение будет таким, как BigMacAttack описал его в комментариях, "плотно вяжущая мозаика сторонних элементов управления HTML" в значительной степени будет на месте. Он должен много походить на полноценное настольное приложение, и HTML, кажется, ненавидит эту идею со страстью. Не то чтобы я виню его.

В любом случае, вот пример кода:

JavaScript:

function exampleElement(caption, content) {
    this.caption = caption;
    this.content = content;
    this.rootElement = document.createElement("div");
}

exampleElement.prototype.constructElement = function() {
    var otherElement = document.createElement("p");
    this.rootElement.className = "exampleElement";
    this.rootElement.textContent = this.caption; 
    otherElement.className = "exampleP";
    otherElement.textContent = this.content;
    this.rootElement.appendChild(otherElement);
    /*I need to know size of the otherElement here*/
    /*here goes code adding stuff into rootElement*/
};

window.onload = function() {
    var ex = new exampleElement("Hello", "Here text");
    ex.constructElement();
    document.body.appendChild(ex.rootElement);
};

CSS

.exampleElement {
    padding: 5px;
    margin: 6px;
}

.exampleElement .exampleP {
    padding: 20px;
    margin: 6px;
}

Скрипка

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

  • создание через новый

  • построение дерева DOM (constructElement)

  • в документ (либо непосредственно в тело, либо в другое дерево DOM)

Важно, чтобы мы знали размеры отдельных элементов на этапе строительства.

До сих пор мы пытались измерить его с помощью атрибутов jQuery, DOM width и height, но ни одно из них не работает с объектом DOM, который не отображается непосредственно на странице. Другой подход, который я пробовал, - это несколько функций, добавляющих объект в document.body, получение ширины и высоты, а затем сразу же его удаление - однако, поскольку наши файлы CSS очень специфичны, это ненадежно, если вы не введете весь rootElement, который будет ужасная производительность и память, поскольку наши компоненты становятся довольно сложными.

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

Запуск баунти, чтобы получить больше идей и предложений. Просто стреляйте в людей, даже если ответ не полностью находится в пределах вопроса (как бы вы это делали и т.д.) - цель, которую я пытаюсь достичь, - это то, что мои JS-сгенерированные элементы управления HTML правильно сочетаются.

4b9b3361

Ответ 1

Получение визуализированной ширины и высоты коробки-модели DOM node с использованием javascript без фактического добавления его в DOM для отображения невозможно.

Чтобы доказать это, пройдите через то, как визуализированная высота и ширина DOM node вычисляется внутри браузера. Я расскажу, как WebKit обрабатывает это, поскольку он является наиболее часто используемым механизмом компоновки.

Когда документ анализируется, а узлы DOM добавляются в "Дерево DOM", Renderers создаются для узлов DOM, которые должны отображаться. Так создается "Render Tree".

Вот выдержка из статьи, озаглавленной "WebCore Rendering я - The Basics" от Dave Hyatt в официальном блоге WebKit:

"Renderers создаются с помощью процесса на DOM, называемого вложением. По мере анализа документа и добавления узлов DOM метод, называемый attach вызывается на узлах DOM для создания рендереров.

void attach()

Метод attach вычисляет информацию о стиле для DOM node. Если свойство CSS для элемента установлено равным none или если nodeпотомок элемента с дисплеем: ни один не установлен, то нет рендерера будет создан".

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

"При вложении DOM запрашивает CSS для получения информации о стиле для элемент. Полученная информация сохраняется в объекте, называемом RenderStyle... Доступ к RenderStyle можно получить из RenderObject используя метод style()... Один из основных подклассов рабочей лошади RenderObject - RenderBox. Этот подкласс представляет объекты, которые подчиняться модели CSS box. К ним относятся любые объекты, имеющие границы, заполнение, поля, ширина и высота."

Итак, если ваш прецедент позволяет получить высоту и ширину рендеринга коробки-модели с помощью C/С++ непосредственно из браузера и передать ее в код javascript с помощью других средств, вы можете запросить методы высоты и ширины подкласса RenderBox каждого элемента DOM. Это в основном то, как WebKit Developer Tools получает эту информацию.

Ответ 2

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

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

Это может быть что-то простое:

{   visibility:hidden;
    position:absolute;
    left: -9999px;
}

И затем снова установите позицию на статическую или относительную, а видимость - на видимую, когда вы готовы показать компонент.

Скрипка здесь, но там не много: http://jsfiddle.net/gwwar/ZqQtz/1/

Ответ 4

Поскольку вы просили ответить на соответствующие вопросы...

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

Хотя это может сделать вашу структуру DOM немного более раздутой, часто лучше использовать "контейнерные" объекты. Эти объекты не будут иметь границ, дополнений или полей, чтобы сохранить их размеры DOM предсказуемыми. Затем вы можете принудительно расширить дочерний объект в границах контейнера.

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

http://jsfiddle.net/aywS6/

CSS

#container {
    position: absolute;
    margin:0px;
    padding:0px;
    width: 300px;
    height: 100px;
    background: #aaa;
    border: 0 none;
}

#subject {
    position: absolute;
    top: 0px;
    bottom: 0px;
    left: 0px;
    right: 0px;
    padding: 10px 20px;
    background: #aaf;
}

HTML

<div id="container">
    <div id="subject">
        contents...
    </div>
</div>

Ответ 5

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

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

Пересмотрите структуру вашего объекта/метода, если вы хотите управлять этими свойствами.

Посмотрите мой обновление вашей скрипки

$(function ()
{
    var ex = new exampleElement("Hello", "Here text");
    ex.constructElement();
    document.body.appendChild(ex.rootElement);

    $("<span/>")
        .text(" => Width is " + $("div").width() + ", and Height is " + $("div").height())
        .appendTo($("div p"));
});

Ответ 6

Не знаю, помогает ли это, но так как вы запросили любой ответ:) вот что я имею.

У меня была аналогичная проблема, когда я хотел иметь хороший эффект jQuery для изменения размера контейнера HTML до "авто" высоты и ширины в соответствии с внутренним контентом. Идея по-прежнему похожа на то, что некоторые люди уже упомянули здесь: у вас есть контейнер где-нибудь "с экрана", вы помещаете туда свой материал, измеряете размеры и удаляете его. Итак, вот функция, которую я нашел здесь

jQuery.fn.animateAuto = function(prop, speed, callback) {
    var elem, height, width;
    return this.each(function(i, el) {
        el = jQuery(el), elem = el.clone().css({
            "height" : "auto",
            "width" : "auto"
        }).appendTo("body");
        height = elem.css("height"), width = elem.css("width"), elem.remove();

        if (prop === "height")
            el.animate({
                "height" : height
            }, speed, callback);
        else if (prop === "width")
            el.animate({
                "width" : width
            }, speed, callback);
        else if (prop === "both")
            el.animate({
                "width" : width,
                "height" : height
            }, speed, callback);
    });
};

Этот код имеет немного больше, чем вам нужно, но часть, которая вас может заинтересовать, такова:

elem = el.clone().css({
                "height" : "auto",
                "width" : "auto"
}).appendTo("body");
height = elem.css("height")
width = elem.css("width")

Надеюсь, что это поможет

Ответ 7

Если основная проблема заключается в том, что вы не можете получить размер, прежде чем поместить его на экран, я бы рекомендовал создать класс, который позволяет div быть скрытым под фоном страницы. Это должно работать с перекрестным браузером.

.exampleHidden{
    position: absolute;
    z-index: -1;
}

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