Изменение размеров элементов на JQuery

VANHALEN

Новичок
Такая засада есть товарищи. Нынче очень модно и почти обязательно делать адаптивные сайты и чтобы сильно не пользоваться процентами в вёрстке (иногда это просто непозволительно) решил измерять некоторые элементы с помощью JQuery и подгонять размер других элементов, исходя из этих величин. Но столкнулся с одной проблемой. Маленький пример.
Код:
function image_size() {
    var side_size = $(".jshop_list_product .block_product .image_block").width(); //определяем ширину блока
    $(".jshop_list_product .block_product .image_block").css({ 'height' : side_size}); // высота = ширине
}
jQuery(document).ready(function () { image_size(); });
jQuery(window).resize(function () { image_size(); });
Тоесть внутри некого блока находится фотка. Чтобы всё было одинаковой ширины и высоты, замеряем ширину этого блока и подгоняем под него высоту. Так вот иногда при резких движениях, или при загрузке с сильно сжатым окном, он эту измеряемую ширину как буд-то с потолка берёт (обычно намного больше, чем есть). Заметил ещё что, если применять данный скрипт не к блоку, а к фотке, которая в нём находится, то количество подобных глюков значительно уменьшается. Но один из плагинов на сайте, пользуется фоткой товара и должен выводить её в таком виде, что я не могу её сделать например квадратной, или с заданым соотношением сторон, иначе некрасиво будет, так что мне нужно просто уместить её в квадратный блок. Да и по сути то это проблему не решает, а просто уменьшает. Я понимаю, что наверное по хорошему здесь просто нужно поставить какой-то тайм-аут на выполнение, но разве же jQuery(document).ready не является подтверждением того, что документ полностью загружен? Да и тайм-аут всё-таки величина относительная. Как вообще решаются подобные проблемы? Как мне отловить тот момент когда не просто загрузился документ, а ещё чтобы блоки выстроились по ширине и только тогда выполнять скрипт?

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

Yoskaldyr

"Спамер"
Партнер клуба
@VANHALEN, вообще-то надо смотреть испектором какая реальная ширина у ".jshop_list_product .block_product .image_block". Не всегда то что видится таким и является :)
А вообще вместо:
Код:
jQuery(document).ready(function () { image_size(); });
jQuery(window).resize(function () { image_size(); });
лучше делать:
Код:
jQuery(document).ready(function () {
    image_size();
    jQuery(window).resize(function () { image_size(); });
});
Т.е. все события ресайза вешать после полной прогрузки страницы.

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

Но в общем случае согласен с @WMix-ом
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
в CSS есть @media и flex, почитай о них

HTML:
header {
  padding: 3px 10px;
}

@media only screen and (min-width: 35em) {
  header {
   padding: 10px 30px;
  }
}
на больших экранах padding в заголовке больше, на телефонах - меньше
 

VANHALEN

Новичок
Я посоветывал бы тебе не портить верстку скриптами. А искать решение на голом css.
Я бы сам себе посоветовал бы то же самое, но у меня таких решений уже с десяток и все они слегка компромисные.
лучше делать:
Код:
jQuery(document).ready(function () {
image_size();
jQuery(window).resize(function () { image_size(); });
});
Результат тот же.
вообще-то надо смотреть испектором какая реальная ширина
Проблема то в том, что ширина появляется по мере "прорисовки". Вот и скрипт отлавливет состояние ширины блока, когда он ещё не до конца "ужался", либо не до конца "распростёрся".
в CSS есть @media и flex, почитай о них
@media пользую и в хвост и в гриву, но опять же, идея у меня была несколько другая. Про flex обязательно поинтересуюсь.

Идея то была в чём. В настройка магазина есть установка "сколько товаров умещать в одном ряду". Даём скрипту вводную - сколько ширины есть при полностью открытом окне, он делит это на колличество, которое указано в настройках, отнимает отступы у всех, кроме последнего и получает ширину "эталона". потом по мере сжатия, или растяжения, он пересчитывает сколько блоков, близких по ширине к эталонному поместится в ряду и соответственно пересчитывает их ширину, соответсвенно меняя количество блоков в ряду. После реализации это й идеи, в общих чертах всё работало, но с той оговоркой, что глюки с определением ширины родительского блока иногда случались. Из этого я сделал вывод, что он не может 100% определить эту ширину именно отгда, когда мне нужно, вот и пошёл интересоваться, а как это вообще можно сделать. Тут вопрос то стоят просто в универсальности решения.

На чистом CSS, вот сильно упрощённый (отступы тоже относительные) пример http://special4kids.ru
Но так беда то в том, что там я по факту смотрел на контент (сколько примерно занимает места) и руками менял свойства через @media. Работает? Да! Гениально и универсально? Нет!
 

Yoskaldyr

"Спамер"
Партнер клуба
роблема то в том, что ширина появляется по мере "прорисовки". Вот и скрипт отлавливет состояние ширины блока, когда он ещё не до конца "ужался"
Вот почему если и использовать такие костыли на js-е, то использовать троттлинг - тогда все успеет отрисоваться. Хотя и тут тоже надо очень сильно постараться с версткой и скриптами, чтобы css не успевал за изменением размера экрана.
Т.е. на лицо явно набор адовых костылей, к которым добавляется еще один костыль.
Но все равно такие нестандартные поведения надо отслеживать в инспекторе, т.е. когда происходит рефлоу, когда вызывается нужное событие и т.д.
Без всего этого - все советы кроме сделать нормальную верстку будут гаданием на кофейной гуще.
 

VANHALEN

Новичок
троттлинг что это в данном контексте и с чем это едят?
Т.е. на лицо явно набор адовых костылей, к которым добавляется еще один костыль.
Так это не я их понаставил, без меня умельцев полно. В каждом движке JQuery, Bootstrap нахер мне не нужный (у меня своя сетка), Mootols и прочие
Хотя и тут тоже надо очень сильно постараться с версткой и скриптами, чтобы css не успевал за изменением размера экрана
Так ширина блока не указана в css. CSS правило для высоты скриптом подписывается.. А так, полностью и всецело согласен. Есть лэндинг у меня, на нём подобная техника используется для того, чтобы круг правильный нарисовать, сейчас модно всяекие кружки с мордами внутри.. Там блин, хоть бы раз глюканоло.. Неа. Тоесть если скрипт так чувствителен с весу, скорости и порядку исполнения, то нахрена он типа нужен. Я по последнему пункту и парюсь, как бы его заставить работать совсем совсем в конце, тобы не тупил
 

VANHALEN

Новичок
Код:
jQuery(document).ready(function () { setTimeout("image_size();", 500); });
jQuery(window).resize(function () { setTimeout("image_size();", 500); });
На глаз не заметна особо задержка, глюков пока не заметил.. Потом уменьши до 100 миллисекунд - то же самое, что при открытии в узком окне, что при резком уменьшении окна (перевороте планшета), глюков нет. Если будет работать на реальном серваке, буду пользоваться постоянно. Всего и делов то.
 

WMix

герр M:)ller
Партнер клуба
нарисуй в минималистике чего хочешь добится, нашиши задачу (не решение) может и найдутся знатоки
 

VANHALEN

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

Меня очень не устраивали относительные отступы при адаптивной вёрстке, поэтому я решил запустить при загрузке ява скрипт, который "померяет сколько у нас в блоке места" и сделает те же расчёты в абсолютных велицинах (в пикселах), которые я бы сделал при обычной вёрстке и будет пересчитывать их на ходу, меняя ширину, высоту и всё что я захочу. Но столкнулся с тем, что иногда он начинает это делать несколько раньше, чем на странице прорисуется родительский блок. Вроде как документ загружен, но ширина блока на долю секунды может быть больше, или меньше. Задача состояла в том, чтобы с помощью того же скрипта убедиться в том, что не просто документ весь загрузился, а в том, что и все все блоки выстроились на странице и можно померять например ширину родительского блока. Как то так.

Я временно решил так, что просто поставил задержку в 100 - 200 миллисекунд перед тем как измерять. Вроде пока не глючит, но я бы предпочёл именно убедиться, что страница прорисована. Есть ли в ява скрипте такое событие?

P.S.
И кстати

Я посоветывал бы тебе не портить верстку скриптами
Ну да, бесконечные использования jQuery для всяких плюшек, это ли не есть вмешательство в вёрстку? Так что одним больше, одним меньше...
 

AnrDaemon

Продвинутый новичок
Меня очень не устраивали относительные отступы при адаптивной вёрстке, поэтому я решил запустить при загрузке ява скрипт, который "померяет сколько у нас в блоке места" и сделает те же расчёты в абсолютных величинах (в пикселах), которые я бы сделал при обычной вёрстке и будет пересчитывать их на ходу, меняя ширину, высоту и всё что я захочу.
Тебе сразу сказали, не надо так делать. Надо по возможности использовать именно относительные величины. em, ex, проценты.
 

VANHALEN

Новичок
Тебе сразу сказали, не надо так делать. Надо по возможности использовать именно относительные величины. em, ex, проценты.
:) Это утверждение противоречит моей задаче. Зачата то как раз состоит в том, что НУЖНО! А решений с относительными величинами у меня уже вагон и маленькая тележка. И ещё.. Сами же правильно написали "По возможности". Да и рабочее вроде как моё решение оказалось.

Вот решил разбить акуратно витрину на блоки одинаковой ширины. Задаём ширину меньше которой мы не хотим сжимать блок. Чтобы всё настраивалось в одном месте, отспуты тоже там прописал. И понеслось
Код:
function smartColumns() {    
    $("#comjshop_list_product").css({ 'width' : "100%"}); //сброс ширины строки до 100% после изменения размера экрана
    var colDefaultWidth = 200; // Приблизительно такой ширины, но не меньше, мы хотим видеть блоки
    var colMargin = 10; // И вот именно точно такие отступы. Пиксель в пиксель, вне зависимости от ширины окна
    var rowWidth = $("#comjshop_list_product").width(); // определяем ширину строки
    var colQuantity = Math.floor(rowWidth / colDefaultWidth); // Смотрим сколько блоков, приблизительно равных ширине по умолчанию, посместится в наш родительский блок
    var allMargins = ((colQuantity - 1) * colMargin); // Подсчитываем сумму всех отступов в ряду, учитывая что после последнего блока отступа не будет
    var colWidth = Math.floor((rowWidth - allMargins) / colQuantity); // Отняли от общей ширины сумму всех отступов

    // Здесь по идее отлавливаем каждый элемент, который отказался последним в ряду, убираем ему отступ справа и прилепляем к правому краю для красоты, иначе иногда из-за откругления, лишний пиксель остаётся.И вот как бы покрасивше отловить это?

    $("#comjshop_list_product .block_product").css({ 'width' : colWidth, 'margin-right' : colMargin, 'margin-top' : colMargin}); //ставим точную ширину измененным столбцам
}

jQuery(document).ready(function () { setTimeout("smartColumns();", 200); });
jQuery(window).resize(function () { setTimeout("smartColumns();", 200); });

jQuery(document).ready(function () { setTimeout("smartColumns();", 200); });
jQuery(window).resize(function () { setTimeout("smartColumns();", 200); });
Поможет кто нибудь отловить последний в ряду блок? В купе с предыдущим костылём, выглядит эффектно и даже вроде не тормозит

P.S. Хотя не могу не согласиться с тем, что с точки зрения экономии ресурсов, нужно было просто упустить неходовые (промежуточные) значения, просто всё просчитать попиксельно и через @media нахреначить правил для 1280px, 1024px, 800px, 640px, 600px, ну и какие там ещё девайсы ходовые есть...
 
Последнее редактирование:

VANHALEN

Новичок
Код:
$("#comjshop_list_product .block_product:nth-child(4n)").css({'float' : 'right', 'clear' : 'right', 'width' : colWidth, 'margin-right' : '0px', 'margin-top' : colMargin});
Вот такое вот CSS решение. Правда IE7, IE8 идёт лесом. Как синтаксически правильно вставить вместо 4 переменную javascript? И так пробовал и сяк, запутался в этих кавычках.
 

VANHALEN

Новичок
Всё, разобрался сам.. Всё прекрасно работает. Даже в IE 8 всё выравнивает шикарно. Спасибо всем за подсказки!
 

hell0w0rd

Продвинутый новичок
Ребята, есть задача, как ее решить?
О, новые интересные словечки... интересно.
А, похер, говнокод работает. Всем спасибо, все свободны.
 

Adelf

Administrator
Команда форума
Мне больше понравилось как он в двух кавычках запутался :) Потому что код в одну строку написал.
 

VANHALEN

Новичок
Ребята, есть задача, как ее решить?
О, новые интересные словечки... интересно.
А, похер, говнокод работает. Всем спасибо, все свободны.
Ну и что тут криминального, в том что я сам всё решил и по ходу решения поделился своими мыслями? Никто вроде пока не захотел предложить не говнокод. А по сему, имею право считать свой велосипед достойным.
Мне больше понравилось как он в двух кавычках запутался :) Потому что код в одну строку написал.
Я не просто запутался, я этот javascript просто в принципе не знаю. Ну всё-таки выкрутился? А как будет в две, в три? И в чём преимущетсва?

Тема вроде пока не закрыта, можете предлагать варианты. А пока да, говнокод.
 
Сверху