HAML. Сборник рецептов

Развивая тему использования полюбившегося мне и моим коллегам инструмента для верстки, я предлагаю вам еще одну заметку о HAML. Ниже будут примеры кода, часть которых выдернута из контекста повседневных задач, другие навеяны вопросами, полученными мною по материалам предыдущих заметок. Так или иначе, все примеры должны оказаться полезными и вы без труда найдете им применение.

  • Передача массива в подключаемый файл
  • Многострочный JavaScript
  • Сброс кэширования файла стилей и скриптов
  • Пользовательские функции
  • Многострочные массивы
  • Получение элемента массива по индексу
  • Массивы с внутренним счетчиком
  • Псевдослучайные числа




Передача массива в подключаемый файл

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

Передача массива выглядит следующим образом:

= Haml::Engine.new(File.read('./inc/file.haml')).render(parent, :add_scripts => ['./assets/js/somescript.min.js', 'http://example.com/someone.js'])

Подключаемый файл file.haml содержит следующий код:

- add_scripts.each do |script|
  %script{src: "#{script}"}

В принципе, этого достаточно для решения задачи, но если возможна ситуация, когда файл file.haml может подключаться без передачи переменной add_scripts, получим ошибку компиляции, говорящую о том, что переменная add_scripts не существует. Решение очень простое — проверять существование переменной и выполнять цикл только в том случае, если она объявлена.

- if defined? add_scripts
  - add_scripts.each do |script|
    %script{src: "#{script}"}

Многострочный JavaScript

Для корректного включения в тело HTML документа JavaScript кода необходимо использовать фильтр :javascript

:javascript
  jQuery(function($) {
  });

Такой код не только компилируется в нормальный многострочный javascript, но и сохраняет полноценную подсветку синтаксиса в IDE (не во всех, безусловно, но IDEA и её младшие браться-сестры справляются).

Есть и другие фильтры, но мы им применения не нашли (не было необходимости), поэтому, кроме нескольких, отдельно упоминать их не стану, а кому интересно, найдут их в официальной документации.

Сброс кэширования файла стилей и скриптов

Если вы показываете клиенту промежуточные результаты верстки, уверен, приходилось слышать комментарии о том, что с предыдущей демонстрации ничего не изменилось или страничка «поехала». Причина, как правило, одна — у клиента попали в кэш подключаемые файлы стилей и скриптов. Чтобы избавить себя от подобных вопросов, в пути подключения всех внешних ресурсов мы добавили динамический параметр. Прием существует столько, сколько существует Интернет, но при использовании HAML он очень удобен и позволяет навсегда забыть о необходимости контролировать ситуацию.

- add_scripts.each do |script|
  %script{src: "#{script}?#{Time.now.strftime("%m%d%y%M%S")}"}

В html мы получим примерно следующее:

<script src="./assets/js/somescript.min.js?0917155512"></script>
<script src="http://example.com/someone.js?0917155512"></script>

Пользовательские функции

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

Если быть точным, то данный фильтр позволяет не просто создавать функции, а встраивать Ruby код в haml файл. Все, что будет «отфильтровано» с помощью фильтра :ruby, парсится с помощью Ruby интерпретатора и выполняется в том же контексте, что и haml код. Это значит, что созданная в фильтре, например, переменная будет доступна в любом месте шаблона (ниже после инициализации).

Пример функции, с помощью которой мы вставляем иконки от Fontawesome.

:ruby
  def fa_icon(name)
      html = '<i class="fa fa-' + name + '"></i>'
      return html
  end

= fa_icon('bomb');

Вызов fa_icon('bomb') дает ожидаемый результат:

<i class="fa fa-bomb"></i>

Многострочные массивы

В целом, это еще один пример использования фильтра :ruby, суть которого раскрыта выше. Но так как мне задавали вопросы именно по созданию многострочных массивов, вынес его отдельным пунктом.

Имея в своем распоряжении всю мощь руби, мы можем создавать не только многострочные массивы, с которыми банально удобнее работать, но и массивы объектов, например.

:ruby
  sidebar_menu = [
    {'id' => 'search', 'icon' => 'icon-magnifier', 'text' => 'Search', 'url' => 'search'},
    {'id' => 'device', 'icon' => 'icon-drawer', 'text' => 'Device', 'url' => 'device'},
    {'id' => 'profiles', 'icon' => 'icon-book-open', 'text' => 'Profiles', 'url' => 'profiles'},
    {'id' => 'settings', 'icon' => 'icon-book-open', 'text' => 'Settings', 'url' => 'settings'}
  ]

- sidebar_menu.each do |item|
  %li
    %a{href: "./#{item['url']}.html"}
      %i{class: "#{item['icon']}"}
      #{item['text']}

Получим следующий html:

<li>
  <a href="./search.html">
    <i class="icon-magnifier"></i>
    Search
  </a>
</li>
<li>
  <a href="./device.html">
    <i class="icon-drawer"></i>
    Device
  </a>
</li>
<li>
  <a href="./profiles.html">
    <i class="icon-book-open"></i>
    Profiles
  </a>
</li>
<li>
  <a href="./settings.html">
    <i class="icon-book-open"></i>
    Settings
  </a>
</li>

Получение элемента массива по индексу

Верстка — не программирование, конечно, и необходимость работать с элементами массива по индексу встречается нечасто. Тем не менее, иногда необходимо получить последний элемент массива. Для этого можно обратить к нему по индексу -1.

- colors = ['007896', '777361', '418f29', '35b890', 'ed3220', 'ffc700', 'ffffff', '0741ab', '0b0b0b']
= colors[-1] # выведет 0b0b0b
= colors[2] # выведет 418f29

Массивы с внутренним счетчиком

Внутренний счетчик — индекс элемента массива на текущей итерации цикла. Позволяет не создавать дополнительных переменных для отслеживания индекса текущего элемента. Удобно использовать совместно с условными операторами при формировании сеток элементов нужного размера.

- (0...5).each_with_index do |item, index|
  = index
-# выведет 0 1 2 3 4

Используя свойство size объекта массива мы получим количество элементов в массиве. В сочетании с внутренним индексом это позволяет определить последнюю итерацию цикла при обходе массива.

- array = ['cat', 'dog', 'fly', 'mouse'];
- array.each_with_index do |item, index|
  - if index == array.size-1
    last element is "#{item}"

Псевдослучайные числа

Крайне удобная возможность, в сочетании с массивами, позволяющая решать множество задач, встречающихся при верстке. Для генерации псевдослучайного числа используется функция rand(), принимающая в качестве параметра целое число, определяющее максимальное значение псевдослучайного числа или Range. Также может быть вызвана без параметра, что равно вызову rand(0).

= rand() # вернет число вида 0.2769118273184681
= rand(0..10) # вернет число из диапазона от 0 до 10 включительно
= rand(0...10) # вернет число из диапазона от 0 до 9

Где применять? Например, необходимо вывести набор checkbox’ов, где у каждого будет свой label, активирующий checkbox.

- ['007896', '777361', '418f29', '35b890', 'ed3220', 'ffc700', 'ffffff', '0741ab', '0b0b0b'].each do |item|
  - input_id = rand(1..99999)
  %input.filter-checkbox{type: 'checkbox', id: "filter_id_#{input_id}"}/
  %label.label-checkbox{for: "filter_id_#{input_id}", style: "background-color: \##{item}"} ##{item}

Здесь мы имеем массив с набором цветов в шестнадцатеричном формате. Каждому должен соответствовать один checkbox и связанный с ним label. Сохранение вызова rand() в переменную input_id позволяет создать уникальные ID для чекбоксов и использовать их в параметре for тэга label.

- (1..12).each do |item|
  - image_id = rand(1..3)
  .product
    %a{href: '#'}
      %img.product-image{src: "./placeholders/b-catalog-grid-image-#{image_id}.jpg", width: 227, height: 289, alt: ''}/

По коду видно, что имена подключаемых изображений отличаются лишь индексом, который мы определяем псевдослучайным числом из диапазона от 1 до 3 включительно. Такая сетка будет смотреться более привлекательно.

Заключение

Пожалуй, это все основные приемы, встречающиеся в нашей повседневной работе. Комбинирование этих приемов позволяет существенно экономить время, которое тратится на верстку средних и крупных проектов. На небольших задачах, вероятно, эффект будет не таким заметным, но мы настолько привыкли к HAML, что верстать непосредственно HTML код уже давно не пробуем, чего и вам советую :)

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *