понедельник, 6 сентября 2010 г.

[Blogger.com] Скрытие сообщений в блоге

Заметка Постраничная разбивка против плагиата в блоге addstips-site.blogspot.com натолкнула меня на мысль попытаться реализовать аналог постраничной разбивки сообщений для блогов на Blogspot. Идея следующая: если бы могли скрыть часть сообщений из потока сообщений на главной странице, страницах поиска (к которым относятся также страницы с выборкой по тегам и т.п.) и в архиве, то такие скрытые сообщения мы могли бы использовать как отдельные страницы для длинных статей, оставляя в заглавном посте только краткое вступление и оглавление.

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

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

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

В выбранном нами шаблоне находим код, отвечающий за выдачу сообщений. В моих экспериментах я использовал стандартный шаблон Simple ((с) Josh Peterson).

    <b:loop values='data:posts' var='post'>
      <b:if cond='data:post.isDateStart'>
        <b:if cond='data:post.isFirstPost == &quot;false&quot;'>
          &lt;/div&gt;&lt;/div&gt;
        </b:if>
      </b:if>
      <b:if cond='data:post.isDateStart'>
        &lt;div class=&quot;date-outer&quot;&gt;
      </b:if>
      <b:if cond='data:post.dateHeader'>
        <h2 class='date-header'><span><data:post.dateHeader/></span></h2>
      </b:if>
      <b:if cond='data:post.isDateStart'>
        &lt;div class=&quot;date-posts&quot;&gt;
      </b:if>
      <div class='post-outer'>
      <b:include data='post' name='post'/>
      <b:if cond='data:blog.pageType == &quot;static_page&quot;'>
        <b:include data='post' name='comments'/>
      </b:if>
      <b:if cond='data:blog.pageType == &quot;item&quot;'>
        <b:include data='post' name='comments'/>
      </b:if>
      </div>
      <b:if cond='data:post.includeAd'>
        <b:if cond='data:post.isFirstPost'>
          <data:defaultAdEnd/>
        <b:else/>
          <data:adEnd/>
        </b:if>
        <div class='inline-ad'>
          <data:adCode/>
        </div>
        <data:adStart/>
      </b:if>
      <b:if cond='data:post.trackLatency'>
        <data:post.latencyJs/>
      </b:if>
    </b:loop>

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

<b:includable id='post1' var='post'>
      <div class='post-outer'>
      <b:include data='post' name='post'/>
      <b:if cond='data:blog.pageType == &quot;static_page&quot;'>
        <b:include data='post' name='comments'/>
      </b:if>
      <b:if cond='data:blog.pageType == &quot;item&quot;'>
        <b:include data='post' name='comments'/>
      </b:if>
      </div>
      <b:if cond='data:post.includeAd'>
        <b:if cond='data:post.isFirstPost'>
          <data:defaultAdEnd/>
        <b:else/>
          <data:adEnd/>
        </b:if>
        <div class='inline-ad'>
          <data:adCode/>
        </div>
        <data:adStart/>
      </b:if>
      <b:if cond='data:post.trackLatency'>
        <data:post.latencyJs/>
      </b:if>
</b:includable>

Добавляем в код внутри цикла условие для показа и скрытия сообщений, которое будет вызывать созданный сегмент:

    <b:loop values='data:posts' var='post'>
      <b:if cond='data:post.isDateStart'>
        <b:if cond='data:post.isFirstPost == &quot;false&quot;'>
          &lt;/div&gt;&lt;/div&gt;
        </b:if>
      </b:if>
      <b:if cond='data:post.isDateStart'>
        &lt;div class=&quot;date-outer&quot;&gt;
      </b:if>
      <b:if cond='data:post.dateHeader'>
        <h2 class='date-header'><span><data:post.dateHeader/></span></h2>
      </b:if>
      <b:if cond='data:post.isDateStart'>
        &lt;div class=&quot;date-posts&quot;&gt;
      </b:if>
      <b:if cond='data:post.labels'>
        <b:include name='post1' data='post'/>
      <b:else/>
        <b:if cond='data:blog.pageType == &quot;item&quot;'>
          <b:include name='post1' data='post'/>
        <b:else/>
          <b:if cond='data:blog.pageType == &quot;static_page&quot;'>
            <b:include name='post1' data='post'/>
          </b:if>
        </b:if>
      </b:if>
    </b:loop>

Готовый результат можно посмотреть в тестовом блоге.

Какие подводные камни и проблемы возможны у такого метода:

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

Скрытые сообщения всё равно видны в виджете Архив.
Решение 1. Не использовать древовидное представление для виджета Архив. В плоском представлении убрать из шаблона виджета отображение количества сообщений, поскольку оно не соответствует числу видимых сообщений. (Пример там же.)
Решение 2. Не использовать виджет Архив, реализовать навигацию по архиву через гаджет на javascript с умной фильтрацией сообщений.

Скрытые сообщения видны в RSS.
Решение: Фильтровать RSS при помощи Yahoo Pipes. О применении Yahoo Pipes я напишу отдельную статью в неопределённом будущем.

Комментарии на разных фрагментах многостраничной  статьи.
Скорее всего, стоит разрешить комментарии только для одной из частей многостраничной статьи.


Модифицированный код шаблона Simple (включая исправление для виджета Архив) можно посмотреть здесь.

Update. Исправлена ошибка в условии, приводившая к скрытию статичных страниц. Спасибо вот этой статье за то что вовремя попалась мне на глаза и позволила сообразить, что такая ошибка имеет место.

3 комментария

Multiкрыса

Дополнение к «можно скрыть сообщения, помеченные определённым ярлыком»:
<b:if cond='data:post.labels'>
<b:loop values='data:post.labels' var='label'>
<b:if cond='data:label.isLast == "true"'>
<b:if cond='data:label.name != "МЕТКА"'>
<b:include data='post' name='post1'/>
</b:if>
</b:if>
</b:loop>
<b:else/>
<b:if cond='data:blog.pageType == "item"'>
<b:include data='post' name='post1'/>
<b:else/>
<b:if cond='data:blog.pageType == "static_page"'>
<b:include data='post' name='post1'/>
</b:if>
</b:if>
</b:if>

Natalya

А вот за «можно скрыть сообщения, помеченные определённым ярлыком» отдельное спасибо.

sgushhenka

Помогите разобраться с возможностью скрыть сообщения, помеченные определённым ярлыком. То есть оказалось, что это таки возможно?
Правильно ли я понимаю, что в предложенном коде вместо МЕТКА нужно вписать название нужного ярлыка? Как выглядит правильное названия ярлыка для кода? Что-то еще нужно в коде менять? И после какой строчки нужно вставлять этот код?
И где будут отображаться сообщения с этим ярлыком? Допустим, у меня есть специальная страница для сообщения с определенным ярлыком. Если я их строю предложенным Вами способом, то на этой странице они останутся или тоже исчезнут?

Отправить комментарий