Каждый день теплого лета дарит все новые радости. Стоит сказать, что разработка второй версии cogear вступила в активную фазу, и то что получается несказанно радует вашего скромного слугу. Тем временем работа с первой версией cogear тоже приносит много положительных эмоций, в силу легкости создания своих шестеренок и тем оформления. Как раз о последнем мы с вами сейчас и поговорим, а заодно позвольте представить вам новую тему оформления движка по-умолчанию.Цель
Как всегда, прежде чем за что-то браться, просто необходимо поставить задачу.Нам нужна современная тема оформления, которую можно будет легко настроить под себя, поменяв несколько изображений (фон, логотип и т.д.) на собственные.
Ресурсы
Откровенно скажу, что не являюсь ярым поклонником резиновой верстки, ибо иногда она вызывает чувство неуверенности в сайте, поэтому в данном случае мы выберем фиксированную ширину, а вместе с ней и замечательный CSS-фреймворк 960.gs.Структура папок
Она идентична исходной. Старая тема просто переименована в simple.Все как обычно. Определяем глобальные части шаблона, меняем стили, доводим до ума настройкой переопределенных стилей и шаблонов шестеренок./templates/default/
css/ — стили
js/ — скрипты
header.tpl — шапка
footer.tpl — подвал
images/ — изображения
...
gears/ — переопределение скриптов и стилей шестеренок
form/
... — см. структуру реальной папки
global/
...
search/
...
sidebar/
css/
widget.css — переопределение стилей
templates/
sidebar.tpl — переопределение шаблона
Обратите внимание
Хотелось бы обратить особое внимание на некоторые вещи.960.gs
Кидаете три файла (960.css, text.css, reset.css) в папку со стилями темы, и они подхватываются движком автоматически.В другом движке пришлось бы прописывать пути к файлам вручную. Мелочь, но как приятно…960.gs позволяет легко и просто создать модульную сетку при помощи div-ов c нужными классами.
Если кто не в курсе — все стили и скрипты автоматически склеиваются в нужном порядке в два отдельных файла. Таким образом пользователь расходует под одному запросу на стили и скрипты. Также стоит отметить, что при внесении изменений с любые скрипты и стили, выходные скомпилированные файлы обновляются автоматически.
Визуально в ширину страница делится на 12 (16, 24 —при желании) секторов, и вы просто создаете div-ы, отмечая их нужными классами(по количеству занимаемых блоков в ширину — «grid_3»,«grid_12», например), а фреймворк автоматически делает за вас кросс-браузерную разметку.
Рекомендую посетить официальный сайт фреймворка, если кто с ним еще не знаком, и приобщиться к этому чуду. Также есть резиновая версия, на ее тему можно погуглить, добавив к называнию фреймворка суффикс «fluid».
В общем виде, верстка страницы блога под 960.gs выглядит так:
...
<!-- Класс обертка идет сверху -->
<div class="container_12">
<div class="grid_12" id="header">...</div>
<!-- Линейка закончилась, новая "строка" берется автоматически -->
<div class="grid_8" id="content">...</div>
<div class="grid_4" id="sidebar">...</div>
<!-- Линейка закончилась, новая "строка" берется автоматически -->
<div class="grid_12"></div>
</div>
...
Переменная шаблона в стилях
Вы можете установить переменную, которая при парсинге стиля будет заменена на путь к шаблону двумя способами, кому как удобнее:
body{
background: url({$tpl}image/background.jpg) repeat-x top left;
background: url(../image/background.jpg) repeat-x top left;
}
Листинги файлов
header.tpl
{*
You can use
{include file="global header"}
to include default site header
*}
{* header *}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
<head>
<title>{$meta.title}</title>
<meta content="text/html; charset={$CI->site->encoding|default:'utf-8'}" http-equiv="Content-Type">
<link rel="shortcut icon" href="http://{$CI->site->url}/favicon.ico" />
{$meta.info}
{$css}
{$scripts}
{$extra}
<script type="text/javascript">
url = 'http://{$CI->uri->url}{if $CI->uri->subdir}/{$CI->uri->subdir}/{/if}';
</script>
</head>
{* /header *}
<body>
<div id="cpanel-holder">{$cpanel}</div>
<div class="container_12">
<div id="header" class="grid_12">
<div class="grid_4 alpha">
<a href="http://{$meta.url}/"><img src="{$tpl}/images/logo.png" border="0" align="left" alt="{$meta.title}" width="300" height="95" id="logo"/></a>
</div>
<div class="grid_8 omega">
</div>
</div>
[<div class="grid_12 alpha omega">{$menu.main}</div>]
<div id="wrapper" class="grid_12">
{if $twitter}
<div id="twitter">
<div id="birdy"><a href="http://twitter.com/{$CI->gears->twitter->login}"><img src="{$tpl}images/twitter.png" alt="Twitter" width="48" height="48"/></a></div>
<div id="tweet">
<div id="tweet-open"> </div>
<div id="tweet-body">{$twitter}</div>
<div id="tweet-close"> </div>
</div>
</div>
{/if}
<div id="content" class="grid_{if $sidebar}8{else}12 omega{/if} alpha">
footer.tpl
</div>
{$sidebar}
<div id="statistics" class="centered grid_8 alpha">
<span class="counter">
</span>
</div>
<div id="footer" class="grid_4 omega">
<p><a href="http://cogear.ru"><img src="http://cogear.ru/uploads/cogear-powered.gif" alt="Работает на cogear" width="70" height="19" align="absmiddle"></a> © {?date('Y')}
<small>Использование памяти: {$mem_usage}
{if !empty($CI->db)}Запросов к базе данных: {? count($CI->db->queries)}
{/if}Запросов в кеш: {? $CI->cache->counter}
Время работы: {? $CI->benchmark->elapsed_time()}</small></p>
</div>
</div>
</div>
{*
You can use
{include file="global footer"}
to include default site header
*}
{* footer *}
</body>
</html>
{* /footer *}
gears/global/templates/cpanel.tpl
{if !$CI->user->is_logged}
<div class="hidden">
<div id="login-form">
<form method="post" id="quick-login" action="/user/login/">
<div class="field">
<label for="login">
Электропочта или логин *
</label>
<input type="text" class="text validate['required']" name="login" id="login">
</div>
<div class="field">
<label for="password">
Пароль *
</label>
<input type="password" size="25" class="password validate['required']" name="password" id="password"> </div>
<div class="field">
<label for="save_cookies" class="small">
Запомнить?
</label>
<input type="checkbox" class="checkbox " name="save_cookies" id="save_cookies">
<a href="/user/lostpassword/">Забыли пароль?</a>
<a href="/user/register/">Регистрация</a>
<a href="/user/openid/"><img height="32" width="32" align="absmiddle" alt="OpenID" src="/gears/user/img/openid_small.png"></a>
</div>
<span class="button">
<input type="submit" onclick="$('quick-login').getElement('input[name=action]').set('value',this.name);" value="Войти" name="submit" id="submit">
</span>
</form>
</div>
</div>
{/if}
<ul id="cpanel"{if $CI->user->is_logged} class="authorized"{/if}>
{if $CI->user->is_logged}
{foreach $elements as $elem}
<li [id="{$elem.id}" ][class="{$elem.class}"] width="{! if(isset($elem.width)) $elem.width = str_replace('%','',$elem.width)}{$elem.width|default:'10'|}%" {if $elem.align}align="{$elem.align}"{/if}>
{if $elem.link}<a href="{$elem.link}" class="no-decoration">{/if}
{if $elem.type == 'icon'}
<img src="{$elem.data}" {if $elem.data_class}class="{$elem.data_class}"{/if}/>
{else}
<span class="cpanel-number">{$elem.data}</span>
{/if}
{if $elem.link}</a>{/if}
{if $elem.link}<a href="{$elem.link}">{/if}
{$elem.text}
{if $elem.link}</a>{/if}
</li>
{/foreach}
{else}
<li><a href="/user/login/" onclick="loader.elem('login-form',640,480);return false;">войти</a></li>
<li><a href="/user/register/">зарегистрироваться</a></li>
{/if}
</ul>
gears/global/css/cpanel.css
div#cpanel-holder{
height: 25px;
background: url({$tpl}images/cpanel.png) repeat-x top left;
position: fixed;
top: 0px;
left: 0px;
width: 100%;
-moz-box-shadow: 0px 1px 3px #2CCAFF;
-webkit-box-shadow: 0px 1px 3px #2CCAFF;
box-shadow: 0px 1px 3px #2CCAFF;
z-index: 1000;
opacity: 0.85;
}
ul#cpanel{
height: 25px;
color: #fff;
padding: 0;
margin: 0;
}
ul#cpanel li.no-image{
list-style: none;
}
ul#cpanel.authorized li:first-child{
background: none;
padding-left: 4px;
}
ul#cpanel li{
padding: 1px 8px 0px 16px;
margin: 0;
height: 35px;
float: left;
vertical-align: top;
list-style: none;
background: url({$tpl}images/cpanel-li.png) no-repeat top left;
text-shadow: 1px 1px 2px #000;
}
ul#cpanel li span{
text-shadow: 1px 0px 2px #000;
}
#cpanel-charge .cpanel-number{
text-shadow: 1px 1px 2px #FFF;
}
ul#cpanel li a, ul#cpanel li div, ul#cpanel li span{
color: #fff;
text-decoration: none;
vertical-align: top;
position: static;
top: 3px;
border-bottom: 1px solid transparent;
}
ul#cpanel li a:hover{
border-bottom: 1px dotted #fff;
}
ul#cpanel li a.no-decoration, ul#cpanel li a.no-decoration:hover{
border: none;
}
ul#cpanel li img{
margin: 4px 0 0 0;
}
ul#cpanel li img.avatar{
margin: 1px 0 0 0;
}
ul#cpanel li span.cpanel-number{
font-size: 1.2em;
}
gears/sidebar/templates/sidebar.tpl
{if empty($disabled)}
<div id="sidebar" class="grid_4 omega">
{foreach $widgets as $widget}
<div {if $widget.config.nobg}style="background:none;"{/if} class="widget{if $widget.config.class} {$widget.config.class}{/if}" {if $widget.config.id}id="{$widget.config.id}"{/if}>
{if !isset($widget.config.notitle)}<div class="widget-header"><h3>{if !empty($widget.config.title)}{$widget.config.title}{else}{$widget.title}{/if}</h3></div>{/if}
<div class="widget-content">{$widget.content}</div>
</div>
{/foreach}
</div>
{/if}
gears/sidebar/css/widget.css
#sidebar{
padding-top: 30px;
}
#sidebar .widget{
width: 290px;
}
#sidebar .widget .widget-header{
background: #636363 url({$tpl}images/grayscale-bg.png) repeat-x top left;
border: 1px solid #636363 ;
-moz-border-radius-topleft: 8px;
-moz-border-radius-topright: 8px;
-webkit-border-top-right-radius: 8px;
-webkit-border-top-left-radius: 8px;
border-radius-top-left: 8px;
border-radius-top-right: 8px;
}
#sidebar .widget .widget-header h3{
text-shadow: 0 -1px 0 #3F3F3F;
font-size: 1em;
font-family: "Lucida Grande",Verdana,Arial,sans-serif;
padding: 5px 10px;
margin: 0;
color: #FFF;
}
#sidebar .widget .widget-content{
padding: 10px 10px;
margin: 0 0 10px;
font-size: 1.123em;
border-left: 1px solid #DFDFDF ;
border-right: 1px solid #DFDFDF ;
border-bottom: 1px solid #DFDFDF ;
-moz-border-radius-bottomleft: 8px;
-moz-border-radius-bottomright: 8px;
-webkit-border-bottom-right-radius: 8px;
-webkit-border-bottom-left-radius: 8px;
border-radius-bottomleft: 8px;
border-radius-bottomright: 8px;
}
#sidebar .white{
background: #FFFFFF;
width: 290px;
padding: 0;
border: none;
box-shadow: none;
-moz-box-shadow: none;
}
#sidebar .white .widget-header, #sidebar .white .widget-content{
padding: 0;
border: none;
}
#sidebar .noborder, #sidebar .no-border{
border: none;
}
#sidebar .widget h1{
margin: 0 0 5px 0;
font-size: 1.4em;
font-weight: normal;
}
#sidebar .no-padding{
padding: 0;
}
gears/search/css/search_widget.css
#search_widget input#query{
border: none;
background: url({$tpl}/images/search.png) no-repeat top left;
width: 200px;
min-width: 200px;
max-width: 210px;
height: 34px;
padding: 0 0 2px 32px;
font-size: 1em;
}
#search_widget input#search-submit{
border: none;
background: url({$tpl}/images/search.png) no-repeat right -34px;
cursor: pointer;
text-indent: -9999px;
height: 34px;
width: 54px;
line-height: 36px;
}
#search_widget input#search-submit:hover{
background: url({$tpl}/images/search.png) no-repeat right -68px;
}
#search_widget div.field{
margin: 0;
padding: 0;
}
gears/form/css/grid.css
table.grid {
-moz-border-radius-topleft: 15px;
-moz-border-radius-topright: 15px;
}
table.grid td{
padding: 5px 3px;
}
table.grid{
position: relative;
border: 1px solid #7E7E7E;
}
table.grid thead tr td, table.grid-fixed-thead thead tr td{
background: url({$tpl}images/grayscale-bg.png) repeat-x top left;
font-size: 0.95em;
text-shadow: 0 -1px 0 #3F3F3F;
color: #FFF;
}
table.grid tbody tr{
}
table.grid tr.even td{
background: #EBEBEB;
}
table.grid-fixed-thead{
position: fixed;
z-index: 1000;
}
table.grid h1{
text-align: center;
font-size: 1.1em;
}
css/styles.css
body {
background: #000 url({$tpl}images/background.jpg) repeat-x center top;
font-family: 'Trebuchet MS',Arial,Verdana,sans-serif;
padding: 40px 0;
}
#wrapper{
font-size: 105%;
background-color: #fff;
-moz-border-radius:5px 5px 5px 5px;
-webkit-border-radius:5px 5px 5px 5px;
-moz-box-shadow: 0 1px 20px #BBBBBB;
-webkit-box-shadow: 0 1px 20px #BBBBBB;
position: relative;
}
.container_12{
padding-bottom: 20px;
}
#twitter{
position: absolute;
top: -35px;
left: 360px;
width: 600px;
}
#twitter #birdy{
display: inline;
}
#twitter #birdy a{
color: transparent;
}
#twitter #tweet{
position: absolute;
left: 42px;
top: 0px;
}
#twitter #tweet div{
float: left;
}
#twitter #tweet #tweet-open{
background-color: white;
background: url(../images/twitter/box-left.png) no-repeat left top;
width: 16px;
height: 31px;
}
#twitter #tweet #tweet-body a{
text-decoration: none;
color: #2CCAFF;
}
#twitter #tweet #tweet-body a:hover{
text-decoration: underline;
}
#twitter #tweet #tweet-body{
background: url(../images/twitter/box-background.gif) repeat-x left top;
height: 31px;
line-height: 2.6em;
font-size: 0.9em;
padding: 0 2px;
white-space: nowrap;
}
#twitter #tweet #tweet-close{
background: url(../images/twitter/box-right.png) no-repeat left top;
width: 8px;
height: 31px;
}
#content{
padding: 10px;
}
#content.grid_12{
width: 920px;
}
#content.grid_8{
width: 600px;
}
#footer{
text-align: right;
width: 280px;
font-size: 0.85em;
color: #292929;
padding-right: 5px;
padding-bottom: 5px;
}
#footer small{
font-size: 0.779em;
color: #CCC;
}
#statistics{
padding: 40px 0 0 0;
}
#footer img{
vertical-align: middle;
}
a {
color: #031B27;
text-decoration: underline;
}
a:hover {
text-decoration: none;
}
fieldset#info{
width: 100%;
}
p.centered{
padding: 10px;
background: #BFBFBF;
border: 1px solid #9B9B9B;
color: #FFF;
text-shadow: 0px 1px 2px #000;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
blockquote{
background: #F3F9FF;
border: 1px solid #80D3FD;
border-left: 4px solid #80D3FD;
padding: 10px;
margin: 15px;
}
img {
border: none;
}
Результат
В результате мы получили отличную тему оформления, которую можно легко кастомизировать, поменяв фоновое изображение, логотип, картинки и цвета в файлах стилей.Также пришлось заменить некоторые иконки в шестеренках для того, чтобы они вписывались в уменьшенную панель пользователя.
Дистрибутив обновлен, теперь в нем две темы.
Успехов в работе с cogear!


Хотя объективности ради, урок свёлся бы к уроку вёрстки. Потому что в отличии от многих других движков, здесь кроме вёрстки ну почти совсем ничего в шаблоне делать не приходится.
Если есть вопросы а-ля step by step, спрашивайте. Очевидные вещи и ходы решил не озвучивать.
Верстка целиком и полностью по 960.gs — по коду шаблонов все понятно, ничего сложного нет.
Зато есть багрепорт. Попытался ответить в соседней вкладке файрфокса (3.5.11) на комментарий в каталоге. Форма не под комментарием выскочила. Не знаю, то ли там древовидных комментариев и нет, то ли просто так… В общем, отправил комментарий и выскочил нотайс
A PHP Error was encountered Severity: Notice Message: Undefined variable: item Filename: mail/_hooks.php Line Number: 196Переключился на текущую вкладку и увидел ответ на мой коммент. Нажал в свою очередь «ответить» и получил какую-то кашу из html-я. Пришлось жать back & refresh. После этого отправил.
Постараюсь решить.
P.S. Разрываюсь в работе между первой и второй версией движка :-)
С точки зрения пользователя, даже не знаю, что предпочесть, «дайошь новую» или «дайошь поддержку». Хотя полагаю, что рано или поздно старую версию придётся забросить ради более перспективной.
А мне честность не позволяет просить доступ ко второй версии. Потому что в ближайший месяц я не внесу никакого вклада даже по мелочам. Ну разве что как тестировщик.
Только и думаю, что если выйдет в августе, то сайт журнала буду делать сразу на ней.
Смотрю последние изменения в SVN.
Add method to simply clear cache by url.
Сразу некоторый ворнинг. Все деструктивные действия следует делать по POST-запросу, а не по урлу. Даже если у злоумышленника нет доступа в админку, он может подсунуть ссылку на деструктивное действие тому, у кого права есть. А вот подсунуть кнопку гораздо сложнее, особенно если к каждой форме приписывать session_id и при получении POST проверять на наличие оного.
Ну, так, небольшой трюк, чуть-чуть повышающий безопасность.
.node .title a{ text-decoration: underline; color: #336633;Все ссылки становятся зелеными, как отдельно прописать класс например для:.node .title { бла бла бла }.node .title { color: #336633; }меняется цвет стрелочки, а где отдельно поменять цвет названия темы и цвет названия сообщества или личного блога??В своей теме вы можете создать шаблон /templates/ваша_тема/gears/nodes/templates/node.tpl, который переопределит исходный.