ИНН 5260488533
+7 993 435 0226
Нижний Новгород, ул. Гоголя, 45а-13
info@sawtech.ru
Политика обработки персональных данных
Адаптивные таблицы для адаптивных сайтов

Верстка адаптивных макетов для нас в Sawtech и для меня в частности давно не является проблемой. Сложности возникают с конечными (по слогам КО-НЕЧ-НЫ-МИ, не перепутайте порядок букв) пользователями.
Вот дизайнеры нарисовали крутой макет, я его круто сверстал (ага-ага, а ещё я очень скромный) — всё очень очень круто выглядит, а потом вся эта красота разбивается о железобетонную действительность. А именно, заказчик берет и в текст новости добавляет таблицу: «Так информация лучше структурирована». С этим доводом сложно спорить. Это проблема и её нужно решать.
Я вижу пока 2 основных варианта решения.
Создаем в админке сложную структуру полей: одно поле — одна ячейка, а может и что-то сложнее, выбор за тобой. В эти поля администратор, контент-менеджер или просто пользователь будет добавлять данные, а мы уже при выводе со своей стороны обрабатываем эти поля и выводим в блочной версии.
Идеальный случай для разработчика, четкие структуры, легкая обработка и вывод. Сложно обучить пользователей, если предполагается большое число пользователей продукта, то половина не прочитает инструкцию, другая половина найдет способ как поломать всё. Но теоретически так тоже можно.
Тут есть 2 концептуальных направления.
Путь наименьшего сопротивления. Обернуть таблицу в div-блок, который будет автоматически добавлять полосу прокрутки, если таблица уже не помещается в ширину родителя. Много где видел такую реализацию. Вполне жизнеспособно, требует минимальных вложений со стороны разработки. Если решать задачу на уровне php, то регуляркой или еще как-то ищем по тексту таблицу и оборачиваем её в div. Только может быть сложность в работе с DOM или regexp отработает не совсем так как хочется. А можно исполнить решение на js, лично мне кажется, это вообще простым вариантом. Но об это чуть ниже сначала про концепции.
Второй концептуальный путь — пересобрать таблицу на div’ах. На выходе потребуется больше навыков от верстальщика, придется в стилях определить поведение блоков на разных разрешениях — адаптивность как она есть. Так же решается как на php, так и на js. Я пойду путем jquery.
Ой, всё! Я знаю, что jquery фу-фу-фу, но мне так проще, не хочешь не пользуйся.
Хочу в одном плагине реализовать оба подхода, чтобы было.
Допустим имеем такую структуру
<div class="main-content"> <h3>Обернутая таблица</h3> <table class="js-add-wrap"> <tr> <th>Заголовок таблица 2, колонка 1</th> <th>Заголовок таблица 2, колонка 2</th> <th>Заголовок таблица 2, колонка 3</th> <th>Заголовок таблица 2, колонка 4</th> </tr> <tr> <td>А тут может быть очень длинный текст, например машиностроительный</td> <td>Строка 1, запись 2</td> <td>Строка 1, запись 3</td> <td>Строка 1, запись 4</td> </tr> <tr> <td>Строка 2, запись 1</td> <td>Строка 2, запись 2</td> <td>Строка 2, запись 3</td> <td>Строка 2, запись 4</td> </tr> </table> <br /> <br /> <h3>Преобразованная таблица</h3> <table class="js-convert-table"> <tr> <th>Заголовок таблица 1, колонка 1</th> <th>Заголовок таблица 1, колонка 2</th> <th>Заголовок таблица 1, колонка 3</th> <th>Заголовок таблица 1, колонка 4</th> </tr> <tr> <td>А тут может быть очень длинный текст, например машиностроительный</td> <td>Строка 1, запись 2</td> <td>Строка 1, запись 3</td> <td>Строка 1, запись 4</td> </tr> <tr> <td>Строка 2, запись 1</td> <td>Строка 2, запись 2</td> <td>Строка 2, запись 3</td> <td>Строка 2, запись 4</td> </tr> </table> </div>
Первую таблицу будем оборачивать в блок, а вторую будем пересобирать.
Много букв, для вот такого плагина:
(function ( $ ) {
$.fn.adaptiveTable = function ( options ) {
options = $.extend({
addWrap: false
}, options);
var make = function () {
var self = this;
$(document).ready(function () {
if( options.addWrap === true ) {
$(self).wrap('<div class="table-adaptive-wrap"></div>');
return true;
}
// пересоберем
var new_table = $('<div class="table-adaptive"></div>');
$(self).find('tr').each(function () {
new_table.append('<div class="table-adaptive__row">');
$(this).find('td, th').each(function () {
new_table.find('.table-adaptive__row').last().append('<div class="table-adaptive__cell">' + $(this).html() + '</div>');
});
});
$(self).replaceWith(new_table);
})
};
return this.each(make);
};
})(jQuery);
Для общего случая надо еще добавить такие стили
/*****************************************************************************/
/********************* Обертка для обычной таблицы ***************************/
.table-adaptive-wrap {
position: relative;
overflow: auto;
}
/*****************************************************************************/
/******************** Стили для адаптивной таблицы ***************************/
.table-adaptive {
width: 100%;
position: relative;
display: table;
border: 1px solid #ccc;
box-sizing: border-box;
}
.table-adaptive__row {
width: 100%;
position: relative;
display: table-row;
}
.table-adaptive__cell {
position: relative;
padding: 10px;
display: table-cell;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
box-sizing: border-box;
}
.table-adaptive__row:first-child .table-adaptive__cell {
border-top: none;
}
.table-adaptive__cell:first-child {
border-left: none;
}
@media all and (max-width: 800px) {
.table-adaptive, .table-adaptive__cell, .table-adaptive__row {
display: block;
}
.table-adaptive {
border: none;
}
.table-adaptive__row {
border-bottom: 1px solid #ccc;
}
.table-adaptive__row:first-child {
display: none;
}
.table-adaptive__cell {
border: none;
}
}
Вот так незамысловато =) Вызывается как и любой плагин:
$(document).ready(function(){
// Просто обертка
$('.js-add-wrap').adaptiveTable({addWrap:true});
// Сложная структура на дивах
$('.js-convert-table').adaptiveTable();
});
Из настроек только 1 параметр — решить задачу через простую обертку, по умолчанию используется продвинутый вариант. Да, есть нюанс, плагин нормально будет работать только для простых таблиц, когда количество ячеек в каждой строке одинаково. Можно, конечно, его усложнить, чтобы он корректно обрабатывал объединенные ячейки, но не сейчас-не сейчас.
В реализованном виде будет выглядеть так, если «поиграть» с шириной окна браузера, то будут понятно в чем различия.
See the Pen vxeBJY by Ildar Saribzhanov (@ildar_r_saribzhanov) on CodePen.
Завел на github репозиторий для этого плагина. Возможно, буду его модифицировать в процессе, так что, как говорится — следите за обновлениями!
Всем рок!
JQuery плагин для валидации и форматирования денежных значений

Пожеланием заказчика было, чтобы при вводе денежного значения, вводимые символы разбивались по группам разрядов и выравнивались по правому краю.
Выравнивание это меньшая из проблем. Думаю, все понимают, что выравнивание текста в поле ввода ничем не отличается от выравнивания текста в любом другом html элементе. А вот разбиение по разрядам задача интересная.
Первым делом идем в великий и могучий поисковик. Недолгие поиски привели меня к этому плагину. У него даже есть возможность задавать маску для ввода денежных значений. Немного поигравшись я понял, что это не совсем то, что мне нужно: во-первых, жестко задано количество дробных разрядов, ни больше ни меньше; во-вторых, дробная часть сразу отделяется и это вызывает диссонанс при вводе. Если решение не нравится, нужно придумать своё.
Я уже однажды сталкивался с проблемой валидации поля input. Если кратко — это не самая очевидно решаемая задача. В моем случае сам алгоритм решения задачи прост:
Собственно сама логика реализуется вот так:
function format( val ) {
var has_separator = false,
res, int, fraction;
val = val.split(',');
// форматирование целой части
while ( val[0].length > 3 ) {
int = val[0].substr(val[0].length - 3) + ' ' + int;
val[0] = val[0].substr(0, val[0].length - 3);
}
int = val[0] + ' ' + int;
// Последний пробел справа убираем
res = int.replace(/\s$/g, '');
res = res.replace(/^0/g, '');
// форматирование дробной части, при наличии
if( val.length > 1 ) {
has_separator = true;
while ( val[1].length > 3 ) {
fraction += ' ' + val[1].substr(0, 3);
val[1] = val[1].substr(3);
}
fraction = fraction + ' ' + val[1];
// сначала удалим пробел
fraction = fraction.replace(/^\s/g, '');
}
if( has_separator ) {
res += ',';
}
if( fraction !== '' ) {
res += fraction;
}
return res;
}
Вот как бы и чики-бамбони, что в переводе значит PROFIT. И тут вы спросите: «Эй, уважаемый, что за омлет, а где же яйца?!» — как этот код будет работать в рамках html+js. Вот мы и пришли к основной проблеме. Вопрос вот в чем: как использовать вышеописанную функцию? При вводе символа в input происходит ряд событий, которые можно перехватить, это keydown, keypress и keyup. Логичным предположением было, повесить обработчик на keypress и, когда это событие произойдет, передать значение input’а в функцию на обработку. Именно так я и сделал. Осознание ошибки пришло мгновенно: в момент вызова обработчика keypress, в поле ввода еще нет того символа, который мы только что ввели. Сюрприз-сюрприз! Конечно, если вы очень хорошо понимаете событийную модель, для вас это не новость, и для меня это была не новость, но когда идет поток сознания некоторые детали реализации могут ускользать. «И что делать?» — спросите вы, а я вам отвечу! (Обожаю задавать вопросы от вымышленного оппонента). «Терпение, спокойствие, сейчас они появятся». Забегая вперед, скажу, что гений меня в этот момент покинул и решение я придумал не столь изящное как хотелось бы. К черту объяснения, как только происходит событие keypress, запихиваем в обработчик тйамаут с минимальным значением паузы, по истечении которого будет вызвана функция форматирования. Та-да!
$(selector).on('keypress', function ( e ) {
setTimeout(function () {
$(self).val(format($(self).val()));
}, 1);
});
Добавим пару регэкспов в функцию форматирования. Разрешим пользователям вводить любой разделитель, хоть запятую, хоть точку, но в input будем выводить только правильный разделитель, в моем случае это запятая. При форматировании функция добавляет пробелы, их нужно исключить из обработки при форматировании, более того, вообще нужны только цифры и разделить. С функцией форматирования разобрались.
Теперь к обработчику нажатия клавиши. Мы можем узнать какие символы пришли от клавиши и какие коды клавиш, поэтому часть ответственности переложим на основной обработчик. О чем идет речь: если пользователь будет вводить что угодно кроме цифр и точки, то вообще не будем запускать форматирование. Это решается не сложно, но есть одна проблема, хочется чтобы стандартное поведение работало. Мне удобнее работать с клавиатуры, навигация по стрелочкам, клавиши home и end, выделение, копирование и вставка, все это должно работать.
И конечно, же не обошлось без проблем на мобильных устройствах. Они, видимо, плохо понимают все это keypress и иже, но есть еще одно замечательное событие для полей ввода, зовется оно «input». Поэтому для мобильников мы еще добавим обработчик на oninput, и к тому же это событие работает и для вставки (ctrl+V), только поддерживается не везде, поэтому оставим обработку и на keypres.
Заканчиваем мусолить. Вот результат работы, обернутый в jquery плагин.
(function ( $ ) {
$.fn.validMoney = function () {
var make = function () {
var self = this; // перепишем объект
$(document).ready(function () {
var def = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', ','],
// клавиши, которые не влияют [ctrl, end, home, left, right, tab]
access = [17, 35, 36, 37, 39, 9];
$(self).on('keypress', function ( e ) {
// is accessed keys
if( access.indexOf(e.keyCode) >= 0 ) {
return true;
}
// ctrl+A
if( e.keyCode === 65 && e.ctrlKey ) {
return true;
}
// backspace and del
if( e.keyCode === 8 || e.keyCode === 46 ) {
setTimeout(function () {
$(self).val(format($(self).val()));
}, 1);
return true;
}
if( e.ctrlKey ) {
setTimeout(function () {
$(self).val(format($(self).val()));
}, 1);
return true;
}
if( def.indexOf(e.key) >= 0 ) {
setTimeout(function () {
$(self).val(format($(self).val()));
}, 1);
return true;
}
return false;
});
});
self.oninput = function () {
self.value = format(self.value);
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
setTimeout(function () {
$(self).val(self.value);
}, 1);
}
};
function format( val ) {
var res,
int = '',
fraction = '',
has_separator = false;
// точку меняем на запятую
val = val.replace(/\./g, ',');
// оставляем только цифры и запятую
val = val.replace(/[^0-9,]/g, '');
// разделим на целую и дробную части
val = val.split(',');
// форматирование целой части
while ( val[0].length > 3 ) {
int = val[0].substr(val[0].length - 3) + ' ' + int;
val[0] = val[0].substr(0, val[0].length - 3);
}
int = val[0] + ' ' + int;
// Убираем последний пробел справа
res = int.replace(/\s$/g, '');
// и ноль слева
res = res.replace(/^0/g, '');
// форматирование дробной части, при наличии
if( val.length > 1 ) {
has_separator = true;
while ( val[1].length > 3 ) {
fraction += ' ' + val[1].substr(0, 3);
val[1] = val[1].substr(3);
}
fraction = fraction + ' ' + val[1];
// сначала удалим пробел
fraction = fraction.replace(/^\s/g, '');
}
if( has_separator ) {
res += ',';
}
if( fraction !== '' ) {
res += fraction;
}
return res;
}
};
return this.each(make);
};
})(jQuery);
Вызывается как и любой плагин вот так:
$('input').validMoney();
Пока писал этот пост нашел еще ряд багов, поэтому не уверен, что это финальный вариант. Для страждущих на гитхабе создал репозиторий, который может обновляться. Там код с примером, если надумаете его использовать, то лучше брать оттуда.
Есть очень логичный вопрос. Нафига? Зачем мне это было нужно, если хорошо поискать, то можно было бы найти готовый вариант, который бы устроил. Полностью согласен с такой точкой зрения. С маленькой поправкой. Используя готовые решения сторонних разработчиков, есть риск нарваться на какой-то баг, который будет не просто исправить. JQuery плагины сейчас пишутся новичками для новичков, многие разработчики стараются запихать в плагин как можно больше функций, чтобы на выходе получить комбайн. В итоге получается монстр на 5 ног, он может все, но отлаживать его удовольствие ниже среднего. Поэтому некоторые несложные вещи, мне нравится писать самому, плагин, который решает одну задачу. Мне будет потом проще понять, что тут происходит, когда я открою код через N-ное время, а если появится новая фича, то её легко добавить.
Стилизация скролл-бара средствами JavaScript
Тема дизайнерских изысков и пожеланий иногда находится за гранью добра и зла. Но от этого никуда не деться, бывает, что они хотят невозможного. Но я считаю, что можно сделать все (если это не противоречит законам физики), весь вопрос в сложности реализации, а соответственно в сроках решения и как итог — стоимость.
В web’е есть ряд вещей, которые не поддаются стилизации в классическом понимании, т.е. нельзя, используя только CSS, изменить их внешний вид. К таким элементам относятся многие теги формы: селекты, чекбоксы, радио-кнопки. Ранее я уже рассказывал, как стилизовать select. Теперь поговорим, как сделать красивый скролл-бар. Откровенно говоря, я ненавижу такие задачи, которые решаются не очевидно или не стандартно, потому что от браузера к браузеру, или даже от версии к версии браузера или ОС, могут вести себя по разному. Хватит лирики, работаем.
Полная эмуляция на js мне не нравится, т.к. это сложно и если js падает, то возможность пролистывания блока пропадает совсем. Где-то давно я почерпнул следующую идею:

Черный прямоугольник — это область просмотра, например, окно браузера.
Зеленый прямоугольник — это то, что должно прокручиваться. Таким образом, ширина прокручиваемого блока шире области просмотра на ширину скролла, примерно, лучше больше, т.к. в разных браузерах, ширина полосы прокрутки разная. Теперь строим из div’ов визуальное представление скролл-бара и вешаем на него нужные обработчики. Теперь можем задать любой мыслимый стиль для лемента, и если js у пользователя отключен, либо в результате ошибки, он упадет, то пролистать блок все равно будет можно.
Технически я представляю как это все делать, и когда-то даже писал полностью всю обработку сам, но в данном случае мне не хотелось изобретать велосипед. Поискав варианты эмуляции скролла, нашел библиотеку baron. Она меня устраивала более чем, за исключением того, что все обертки и блоки эмуляции нужно вставлять в html. Такой вариант мне казался несколько странным, раз есть плагин, то мне хотелось бы совершать минимум действий, в идеале просто натравить плагин на блок, который надо стилизовать и все, пусть он сам добавляет нужную разметку. Исходя из этого душевного посыла было принято решение написать небольшую обертку, которая подготовит блоки и запустит эмуляцию скролла.
Собственно, код обертки такой:
(function ($) {
$.fn.wrapFoBaron = function (options) {
options = $.extend({
root : '.scroller_wrap',
barOnCls: 'baron'
}, options);
var make = function () {
$(document).ready(function () {
$(options.root).each(function () {
$(this).wrapInner('<div class="scroller__content"></div>');
$(this).wrapInner('<div class="scroller"></div>');
$(this).append('<div class="scroller__bar-wrapper"><div class="scroller__bar"></div></div>');
});
var params = {
root : options.root,
scroller: '.scroller',
bar : '.scroller__bar',
barOnCls: options.barOnCls
};
var scroll = baron(params);
check_size();
check_size();
function check_size() {
$(options.root).each(function () {
if ($(this).find('.scroller__content').height() <= $(this).height()) {
$(this).find('.scroller__bar-wrapper').hide();
$(this).find('.scroller').addClass('.with-scroll');
} else {
$(this).find('.scroller').removeClass('.with-scroll');
}
});
}
})
};
return make();
};
})(jQuery);
И вызываем вот так
$(document).wrapFoBaron({
root: '.class-name',
barOnCls: 'baron'
});
Я даже немного попытался соответствовать идеологии БЭМ. Глядя на код сразу бросается в глаза, что функция check_size вызывается 2 раза подряд, зачем так делается и вообще зачем она? А затем, что кастомный скролл-бар добавляется только тогда, когда это реально необходимо, это ответ на второй вопрос, а на первый вопрос ответ такой: После того как было принято решение, что надо добавить скролл-бар, запускается процесс добавления разметки и в этот момент размеры наружных блоков могут (с большой вероятностью они это сделают) изменится, и чтобы все выглядело адекватно, запускаем процесс инициализации дважды.
Чтобы было проще втянутся в процесс понимания, приведу тут пример стилей одного из наших проектов
.scroller {
height: 100%;
overflow-y: auto;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.scroller::-webkit-scrollbar {
width: 0;
}
.scroller__content {
position: relative;
padding-right: 30px;
overflow: hidden;
}
.scroller__bar-wrapper {
position: absolute;
z-index: 2;
top: 10px;
bottom: 10px;
right: 5px;
width: 8px;
border-radius: 5px;
background-color: rgba(255, 255, 255, 0.5);
pointer-events: none;
-webkit-transition: all 0.2s linear 0s;
-moz-transition: all 0.2s linear 0s;
-o-transition: all 0.2s linear 0s;
transition: all 0.2s linear 0s;
opacity: 0;
}
.scroller__bar {
position: absolute;
z-index: 1;
width: 8px;
border-radius: 3px;
background-color: rgba(0, 0, 0, 0.5);
-webkit-transition: opacity 0.2s linear 0s;
-moz-transition: opacity 0.2s linear 0s;
-o-transition: opacity 0.2s linear 0s;
transition: opacity 0.2s linear 0s;
pointer-events: auto;
opacity: 0;
}
.baron:hover .scroller__bar-wrapper {
opacity: 1;
}
.baron:hover .scroller__bar {
opacity: 1;
}
Реализация, конечно, костыльная, и для мобильных устройств её стоит отключать, но вроде бы везде работает, так что можете пользоваться на здоровье. Кстати, есть небольшой пример вот тут. Пользуйтесь на здоровье =)
С началом нового рабочего года ;)
Верстка плитками и вариант решения на JQuery
Верстка плитками и вариант решения на JQuery
Одним из последних веяний в веб-дизайне, да и в GUI в принципе, является плиточная верстка. Win8 яркий тому пример. Наверное, с точки зрения дизайна это очень клево и стильно. Так уж исторически сложилось, что я не дизайнер, я верстальщик. И вот именно в верстке плитками есть много тонкостей и сложностей.
Сначала выскажу свое видение вариантов такой верстки.
Проблем я не вижу. Жмем блоки друг к другу с помощью float:left и пляшем.
Можно, конечно, воспользоваться таким же вариантом с float:left, но в результате вы получите следующую проблему:
Та-да-да-дан
Это особенности свойства float: left, кстати, если использовать display: inline-block, ситуация будет ровно такой же, поскольку элементы хоть и применяют свойства блочных элементов, но в линию выстраиваются как строчные, т.е. по строкам, такое вот масло масленное.
Но хотелось бы увидеть результат, когда не будет пустых ячеек и нижние три блока поднимуться выше.
Лично я решал эту проблему колоночным вариантом верстки: 4 колонки (или столько колонок, сколько вам нужно) и в них добавляются ваши блоки контента. Выглядеть это будет примерно вот так:
Красота, не правда ли? Конечно, тому кто будет эту верстку притягивать к движку, надо будет как-то заполнять сверстанный макет, но это уже не наша проблема, у нас верстка идеальна. Только, как правило, это наша проблема, а наполнять можно либо по очереди в каждую колонку, но тогда может оказаться, что одна колонка много больше других, что не очень хорошо, либо анализировать высоту колонок и добавлять в ту, высота которой меньше. А вот эту идею надо запомнить, он нам еще пригодится.
Перейдем к последнему типу плиточной верстки
Не совсем различную, а есть некоторый базовый блок, а все остальные имеют размер кратный базовому. По крайней мере, мне хочется верить, что все обстоит именно так =) Как быть тут? Понятно, что вариант 1 и 2 нам не подходят. Но дизайнеры, нормальные дизайнеры, понимают, что можно сделать, а что нельзя. Соответственно, верстальщик может выделить в макете некоторую закономерность или упорядоченность. Сразу приведу пример как я решал проблему неодинаковых блоков.
Так что же тут происходит?
Можно идти очень сложным, но логичным путем, сначала выделяем большой блок, равный одной строке, в нашем случае этот блок будет равен 4 базовых блока в ширину и 2 базовых блока в высоту. Затем, для верхних двух маленьких блоков создаем собственную обертку, чтобы они располагались один под другим. Для верхних правых такая же история.
Я в данном примере, исключил большой блок 2х4, он только загромождает верстку, поэтому структура такая. (Дальше размеры блоков будут обозначаться NxM, где N — ширина в базовых блоках и M — высота в базовых блоках)
В данном примере, структура не очень сложная, но даже заполнение такой верстки, когда она станет шаблоном определенного движка, у меня вызывает некоторые вопросы, особенно, если, вдруг, появится подгрузка контента, т.е. так называемый, бесконечный скролл. Если структура будет сложнее, думаю, вы сами понимаете весь масштаб трагедии, как с точки зрения верстки, так и с точки зрения наполнения этой верстки.
Вот и у меня возникла мысль: «Ну ее нафиг, такую структуру, надо искать плагины плиточной верстки!»
Я не любитель искать, особенно, когда в голове уже сидит идея как можно сделать свой велосипед и по какой логике он должен работать. Вот так и рождаются стопицот квадратноколесых велосипедов.
Есть некоторый стандартный набор элементов: во-первых обертка с классом tile_content, которая наполняется нашими элементами. Затем внутрь обертки помещается много-много необходимых элементов с обязательным классом b_itemtile и еще одним классом, который говорит нашему скрипту о размерах блока b_itemtile_1_1, где первая цифра ширина, а вторая высота. А больше ничего по верстке нет. Круто? Я считаю, что круто! Мне очень нравится такая простая верстка, тем более, что я прямо вижу как классно наполнять эту верстку =)
<div class="tile_content"> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_2_1 b_itemtile"></div> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_2_2 b_itemtile"></div> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_4_1 b_itemtile"></div> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_3_3 b_itemtile"></div> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_1_4 b_itemtile"></div> <div class="b_itemtile_1_3 b_itemtile"></div> <div class="b_itemtile_1_2 b_itemtile"></div> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_3_4 b_itemtile"></div> <div class="b_itemtile_1_1 b_itemtile"></div> <div class="b_itemtile_1_4 b_itemtile"></div> <div class="b_itemtile_4_1 b_itemtile"></div> </div>
А самое классное это количество стилей для этой верстки
.tile_content{position: relative; outline: 1px solid #f00; overflow: hidden;}
.b_itemtile{position: absolute; background: #aaa;}
И все! Все остальное сделает скрипт.
Приводить код скрипта не буду, скажу только, что он работает. И делает это следующим образом. У него есть пока всего 2 настройки: количество колонок и расстояние между блоками. Ну как настройки? В коде скрипта есть две переменные, которые и отвечают за эти параметры.

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

Но если дизайн составлен под руководством здравого смысла, управляемого логикой, то на выходе красота, да и только.
Вот ссылка на архив с рабочим примером. К тому же я потихоньку изучаю Git и дам ссылку на github, есть вероятность, что к моменту прочтения поста, на гитхабе будет версия более похожая на плагин и более функциональна. Хотя меня пока устраивает и этот вариант, мои задачи он выполняет!
Превью видео Youtube
Чтобы получить скриншот (превью) видео нудно обратиться по такому адресу
http://img.youtube.com/vi/[video_id]/[0-3].jpg
video_id -это id вашего видео (неожиданно, правда?), его можно взять в url-адресе видео. Например есть видео по такой ссылке http://www.youtube.com/watch?v=UOQI4lCM-2c, его id = UOQI4lCM-2c.
[0-3] — это цифры от 0 до 3, если указать 0 — получите скриншот размером 480×360, если 1-3 — 120×90, но разные.
Для видео указанно чуть выше, url большой картинки будет таким http://img.youtube.com/vi/UOQI4lCM-2c/0.jpg
Да все просто, если у вас видео-блог или сайт на страницах которого может быть много видео, то скорость загрузки может вас сильно расстроить. Чтобы этого избежать можно брать только превью видео, без загрузки самого видео. Но тут может возникнуть закономерный вопрос: «Ну хорошо, есть у меня превью, а как начать воспроизводить само видео при клике на картинку?» А я вам отвечу: «А это правильный вопрос. Программа завершена.» — в смысле, все достаточно просто. Берем javascript в одну руку (в моем случае jquery), берем ссылку на видео в другую руку и (херачим пока видео не будет воспроизводиться =) ) в блок где была картинка вставляем видео с автозапуском. Как получить ссылку для вставки видео в блог объяснять не буду (все просто, под видео на youtube, есть ссылочка «поделиться», там надо выбрать html-код). Скорее всего вы получите код такого формата
<iframe width="480" height="360" src="//www.youtube.com/embed/UOQI4lCM-2c?rel=0" frameborder="0" allowfullscreen></iframe>
Такое видео не будет играть автоматом, а чтобы заиграло надо добавить к url autoplay=1, вот так
<iframe width="480" height="360" src="//www.youtube.com/embed/UOQI4lCM-2c?rel=0&autoplay=1" frameborder="0" allowfullscreen></iframe>
Вот это видео заиграет сразу после вставки. Кстати, обратите внимание, что url без http: в начале, по большому счету, если это живой сайт, то все будет работать, а вот если это верстка, то надо будет добавить это протокол.
Сначала кусок верстки:
<div class="this_video"> <img class="start_this_video" src="http://img.youtube.com/vi/UOQI4lCM-2c/0.jpg" alt="" /> </div>
И скрипт:
$('.start_this_video').click(function(){
$('.this_video').html('<iframe width="480" height="360"
src="http://www.youtube.com/embed/UOQI4lCM-2c?autoplay=1"
frameborder="0" allowfullscreen></iframe>');
});
Вот и все. Достаточно просто, не правда ли? =)
Приведу рабочий пример на примере все того же видео

Кстати, чтобы получить id изображения из url можно использовать вот такой PHP-код
$url_video = 'http://www.youtube.com/watch?v=aCnIuxvnzAU';
preg_match('%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $url_video, $match);
$Youtube_video_id = $match[1];
До кучи, чтобы можно было поэксперементировать у себя на компьютере, Вот вам ссылка на архив с примером
Отправка формы без перезагрузки страницы
Часто возникает необходимость отправки формы без перезагрузки страницы. В этом случае на помощь приходит технология ajax и фреймворк jQuery.
Например имеем форму следующего вида:
<form method="" name="osForm" action="" id="osForm"> <input class="osForm_input" tabindex="1" id="name" name="name" type="text" value="*Ваше имя" /> <input class="osForm_input" tabindex="2" id="email" name="email" type="text" value="*Ваш email" /> <input class="osForm_input" tabindex="3" id="address" name="address" type="text" value="*Адрес доставки (индекс,область,город,улица,дом,квартира)" /> <input class="osForm_btn" tabindex="4" type="submit" name="sndbtn" value="Отправить" /> </form>
Чтобы отправить эту форму без перезагрузки страницы, используем javascript:
$('#osForm').submit(function(e){
e.preventDefault();
$.ajax({
url: "sendOrderForm.php",
type: "POST",
data: $('#osForm').serialize(),
success: function(response) {
//обработка успешной отправки
},
error: function(response) {
//обработка ошибок при отправке
}
});
});
sendOrderForm.php — файл, который обрабатывает пересылаемые формой данные. Например он может быть таким:
if (isset($_POST['username'])){
$name = $_POST['username'];
$contacts = $_POST['contacts'];
$message = $_POST['message'];
$from = 'no-reply@yandex.ru';
$mailTo='mail@yandex.ru';
$headers = "From: Иван Петров <$from>\nReply-To: $from\n";
$headers .= 'Content-type: text/html; charset=utf-8' . "\r\n";
$message="
<h1>Сообщение с сайта</h1>
<p>Имя: $name</p>
<p>Контакты: $contacts</p>
<p>Сообщение: $message</p>
";
wp_mail($mailTo,"Форма обратной связи",$message,$headers);
}
Полезные куски кода для JavaScript
Поскольку моя основная «специализация» все же верстальщик, то я в основном имею дело с html и javasript. Как было кем-то сказано: «На javascript сначала начинают писать, и только потом начинают его изучать». С этим нельзя не согласиться, по крайней мере на своем примере я это проверил.
Я достаточно ленив и не люблю сложные решения. Поэтому во всех наших проектах используется jquery, да и в стандартном комплекте wordpress, который используется в наших проектах этот фрэймворк идет в комплекте, поэтому я вообще не беспокоюсь о лишних килобайтах.
В прошлый раз я выкладывал коды для WP, теперьм Мне хочется поделиться некоторыми полезными кусочками кода, которые я периодически использую при написании скриптов. И так поехали:
1. Обращение к элементу по его порядковому номеру, отсчет начинается с единицы, нумерация идет слева-направо, сверху- вниз:
$('.carusel_itm:nth-child(' +number_itm + ')').css('opacity','1');
2. Вырезать цифры из строки «stroka»:
$('.carusel_itm:nth-child(' +number_itm + ')').css('opacity','1');
Ну вроде бы тут все понятно, особенно для тех, кто шарит в регулярных выраениях.
3. Получение элемента в наборе, нумерация начинается с нулевого, поэтому добавляем единицу
var index = $(this).index()+1;
4. Поиск подстроки в строке:
str.indexOf('подстрока') + 1
Я использую данное выражение для проверки наличия подстроки в строке. Поясню немного зачем добавляю единицу. Данное выражение по идее предназначено для поиска первого вхождения подстроки в строку, поэтому оно возвращает не булево значение, а номер символа с которого начинается искомая подстрока. Самое интересное, что нумерация символов начинается с нуля, что вполне логично, но не в этом соль, а прикол в том если строка не найдена возвращается -1. В javasript, значение 0 = false, а любое отличное от нуля это true, отсюда и родилась +1. Во-первых подстока может быть в начале и тогда сама функция вернет 0, и.. Ну в общем, все понятно))
Едем далее.
5. Подсчет количества элементов по классу
$('.class').size();
Этот код я достаточно часто использую в галереях, когда необходимо просчитать ширину контейнера, в котором лежат все слайды. Конечно, в большинстве реализация, которые я видел тупо задают ширину 10000em и не парятся, но мне это кажется не особо эстетичным.
6. Проход по всем элементам набора:
$('.class').each(function (i) {
});
Если нужно у что-то сделать не со всеми элементами набора, а лишь с несколькими, выборочно, то я пользуюсь именно этим набором.
7. Данный код выведет текущий url страницы. Можно запихать в переменную и обрабатывать.
alert(document.location.href);
8. Достать первый из дочерних элементов и дальше можно делать все что душе угодно:
$(this).children(':first').any_method()
На этом я хочу пока закончить. Переодически буду добавлять еще что-нибудь, память у меня с прошлого раза лучше не стала)) Поэтому пусть здесь все это лежит. Может и еще кому пригодится. В комментах можете добавлять свои часто используемые коды.
ИНН 5260488533
+7 993 435 0226
Нижний Новгород, ул. Гоголя, 45а-13
info@sawtech.ru