Давно пылится в черновиках красивый примерчик для календаря. В оригинале календарь под хтмл, я приладил для вордпресса, на страницу архивов по месяцам.
Вот тут можно посмотреть календарь в действии, скрин
Сам календарь можно взять отсюда.
Как поставить себе.
Открываем файл functions.php для вашей темы, добавляем функцию
function MyCal(){ global $wpdb, $m, $monthnum, $year, $wp_locale, $posts; $cache = array(); $key = md5( $m . $monthnum . $year ); if ( $cache = wp_cache_get( 'get_calendar', 'calendar' ) ) { if ( is_array($cache) && isset( $cache[ $key ] ) ) { echo $cache[ $key ]; return; } } if ( !is_array($cache) ) $cache = array(); // Quick check. If we have no posts at all, abort! if ( !$posts ) { $gotsome = $wpdb->get_var("SELECT 1 as test FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish' LIMIT 1"); if ( !$gotsome ) { $cache[ $key ] = ''; wp_cache_set( 'get_calendar', $cache, 'calendar' ); return; } } ob_start(); if ( isset($_GET['w']) ) $w = ''.intval($_GET['w']); // week_begins = 0 stands for Sunday $week_begins = intval(get_option('start_of_week')); // Let's figure out when we are if ( !empty($monthnum) && !empty($year) ) { $thismonth = ''.zeroise(intval($monthnum), 2); $thisyear = ''.intval($year); } elseif ( !empty($w) ) { // We need to get the month from MySQL $thisyear = ''.intval(substr($m, 0, 4)); $d = (($w - 1) * 7) + 6; //it seems MySQL's weeks disagree with PHP's $thismonth = $wpdb->get_var("SELECT DATE_FORMAT((DATE_ADD('${thisyear}0101', INTERVAL $d DAY) ), '%m')"); } elseif ( !empty($m) ) { $thisyear = ''.intval(substr($m, 0, 4)); if ( strlen($m) < 6 ) $thismonth = '01'; else $thismonth = ''.zeroise(intval(substr($m, 4, 2)), 2); } else { $thisyear = gmdate('Y', current_time('timestamp')); $thismonth = gmdate('m', current_time('timestamp')); } $unixmonth = mktime(0, 0 , 0, $thismonth, 1, $thisyear); // Get the next and previous month and year with at least one post $previous = $wpdb->get_row("SELECT DISTINCT MONTH(post_date) AS month, YEAR(post_date) AS year FROM $wpdb->posts WHERE post_date < '$thisyear-$thismonth-01' AND post_type = 'post' AND post_status = 'publish' ORDER BY post_date DESC LIMIT 1"); $next = $wpdb->get_row("SELECT DISTINCT MONTH(post_date) AS month, YEAR(post_date) AS year FROM $wpdb->posts WHERE post_date > '$thisyear-$thismonth-01' AND MONTH( post_date ) != MONTH( '$thisyear-$thismonth-01' ) AND post_type = 'post' AND post_status = 'publish' ORDER BY post_date ASC LIMIT 1"); /* translators: Calendar caption: 1: month name, 2: 4-digit year */ $calendar_caption = _x('%1$s %2$s', 'calendar caption'); echo '<table id="wp-calendar" summary="' . __('Calendar') . '" cellspacing="0"> <thead> <tr>'; $myweek = array(); for ( $wdcount=0; $wdcount<=6; $wdcount++ ) { $myweek[] = $wp_locale->get_weekday(($wdcount+$week_begins)%7); } foreach ( $myweek as $wd ) { $day_name = (true == $initial) ? $wp_locale->get_weekday_initial($wd) : $wp_locale->get_weekday_abbrev($wd); echo "\n\t\t<th abbr=\"$wd\" scope=\"col\" title=\"$wd\">$day_name</th>"; } echo ' </tr> </thead> <tfoot> <tr>'; if ( $previous ) { echo "\n\t\t".'<th colspan="3"><a href="' . get_month_link($previous->year, $previous->month) . '" title="' . sprintf(__('View posts for %1$s %2$s'), $wp_locale->get_month($previous->month), date('Y', mktime(0, 0 , 0, $previous->month, 1, $previous->year))) . '">« ' . $wp_locale->get_month($previous->month) . '</a></th>'; } else { echo "\n\t\t".'<th colspan="3"> </th>'; } echo "\n\t\t".'<th> </th>'; if ( $next ) { echo "\n\t\t".'<th colspan="3" style="border-right: 1px solid #9DABCE;"><a href="' . get_month_link($next->year, $next->month) . '" title="' . sprintf(__('View posts for %1$s %2$s'), $wp_locale->get_month($next->month), date('Y', mktime(0, 0 , 0, $next->month, 1, $next->year))) . '">' . $wp_locale->get_month($next->month) . ' »</a></th>'; } else { echo "\n\t\t".'<th colspan="3" style="border-right: 1px solid #9DABCE;"> </th>'; } echo ' </tr> </tfoot> <tbody> <tr>'; // Get days with posts $dayswithposts = $wpdb->get_results("SELECT DISTINCT DAYOFMONTH(post_date) FROM $wpdb->posts WHERE MONTH(post_date) = '$thismonth' AND YEAR(post_date) = '$thisyear' AND post_type = 'post' AND post_status = 'publish' AND post_date < '" . current_time('mysql') . '\'', ARRAY_N); if ( $dayswithposts ) { foreach ( (array) $dayswithposts as $daywith ) { $daywithpost[] = $daywith[0]; } } else { $daywithpost = array(); } if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false || strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'camino') !== false || strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'safari') !== false) $ak_title_separator = "\n"; else $ak_title_separator = ', '; $ak_titles_for_day = array(); $ak_post_titles = $wpdb->get_results("SELECT post_title, DAYOFMONTH(post_date) as dom " ."FROM $wpdb->posts " ."WHERE YEAR(post_date) = '$thisyear' " ."AND MONTH(post_date) = '$thismonth' " ."AND post_date < '".current_time('mysql')."' " ."AND post_type = 'post' AND post_status = 'publish'" ); if ( $ak_post_titles ) { foreach ( (array) $ak_post_titles as $ak_post_title ) { $post_title = esc_attr( apply_filters( 'the_title', $ak_post_title->post_title ) ); if ( empty($ak_titles_for_day['day_'.$ak_post_title->dom]) ) $ak_titles_for_day['day_'.$ak_post_title->dom] = ''; if ( empty($ak_titles_for_day["$ak_post_title->dom"]) ) // first one $ak_titles_for_day["$ak_post_title->dom"] = "<li><span class=\"title\">".$post_title."</span></li>"; else $ak_titles_for_day["$ak_post_title->dom"] .= "<li><span class=\"title\">".$post_title."</span></li>"; } } // See how much we should pad in the beginning $pad = calendar_week_mod(date('w', $unixmonth)-$week_begins); if ( 0 != $pad ) echo "\n\t\t".'<td colspan="'.$pad.'"> </td>'; $daysinmonth = intval(date('t', $unixmonth)); for ( $day = 1; $day <= $daysinmonth; ++$day ) { if ( isset($newrow) && $newrow ) echo "\n\t</tr>\n\t<tr>\n\t\t"; $newrow = false; if ( in_array($day, $daywithpost) ){ // any posts today? echo "<td class=\"date_has_event\"><a href=\"".get_day_link($thisyear, $thismonth, $day)."\" class=\"date_has_event\">$day</a><div class=\"events\"> <ul> $ak_titles_for_day[$day] </ul> </div>"; } if(!in_array($day, $daywithpost)){ if ( $day == gmdate('j', (time() + (get_option('gmt_offset') * 3600))) && $thismonth == gmdate('m', time()+(get_option('gmt_offset') * 3600)) && $thisyear == gmdate('Y', time()+(get_option('gmt_offset') * 3600)) ){ echo '<td>'.$day;} else { echo '<td>'.$day; } } echo '</td>'; if ( 6 == calendar_week_mod(date('w', mktime(0, 0 , 0, $thismonth, $day, $thisyear))-$week_begins) ) $newrow = true; } $pad = 7 - calendar_week_mod(date('w', mktime(0, 0 , 0, $thismonth, $day, $thisyear))-$week_begins); if ( $pad != 0 && $pad != 7 ) echo "\n\t\t".'<td colspan="'.$pad.'"> </td>'; echo ' <thead> <tr>'; $myweek = array(); for ( $wdcount=0; $wdcount<=6; $wdcount++ ) { $myweek[] = $wp_locale->get_weekday(($wdcount+$week_begins)%7); } foreach ( $myweek as $wd ) { $day_name = (true == $initial) ? $wp_locale->get_weekday_initial($wd) : $wp_locale->get_weekday_abbrev($wd); echo "\n\t\t<th abbr=\"$wd\" scope=\"col\" title=\"$wd\">$day_name</th>"; } echo ' </tr> </thead>'; echo "\n\t</tr>\n\t</tbody>\n\t</table>"; $output = ob_get_contents(); ob_end_clean(); echo $output; $cache[ $key ] = $output; wp_cache_set( 'get_calendar', $cache, 'calendar' ); }
Далее открываем файл header.php, добавляем следующее:
<script src="<?php bloginfo('template_directory'); ?>/js/coda.js" type="text/javascript"> </script> <link rel="stylesheet" href="<?php bloginfo('template_directory'); ?>/cal.css" type="text/css" media="screen" charset="utf-8" />
Теперь создаем файл cal.css:
* { border: 0px; padding: 0px; } .capt { padding-top: 20px; font-size: 22px; color: #335; text-align:center; } table { border-collapse: separate; border: 1px solid #9DABCE; border-width: 0px 0px 1px 1px; margin: 10px auto; font-size: 20px; } td, th { width: 81px; height: 81px; text-align: center; vertical-align: middle; background: url(img/cells.png); color: #444; position: relative; } th { height: 30px; font-weight: bold; font-size: 14px; } td:hover, th:hover { background-position: 0px -81px; color: #222; } td.date_has_event { background-position: 162px 0px; color: white; } a.date_has_event { background-position: 162px 0px; color: white; text-decoration:none; } td.date_has_event:hover { background-position: 162px -81px; } td.padding { background: url(img/calpad.jpg); } td.today { background-position: 81px 0px; color: white; } td.today:hover { background-position: 81px -81px; } .events { position: relative; } .events ul { text-align: left; position: absolute; display: none; z-index: 1000; padding: 15px; background: #E7ECF2 url(img/popup.png) no-repeat; color: white; border: 1px solid white; font-size: 15px; width: 200px; -moz-border-radius: 3px; -khtml-border-radius: 3px; -webkit-border-radius: 3px; -border-radius: 3px; list-style: none; color: #444444; -webkit-box-shadow: 0px 8px 8px #333; } .events li { padding-bottom: 5px; } .events li span { display: block; font-size: 12px; text-align: justify; color: #555; } .events li span.title { font-weight: bold; color: #222; } a.next_month { background-position: 162px 0px; color: #444; text-decoration:none; } th.month{ background: none } tfoot { background: url(img/tfoot.gif); } th.padding{ background: transparent; }
И правим файл archive.php так, чтобы при is_month выводился только календарь, else все остальное. Мой archive.php:
<?php get_header(); ?> <div id="posts"> <?php if (is_month()) { ?> <h1>Записи за <?php the_time('F, Y'); ?></h1> <?php MyCal(); ?> </div> <?php get_sidebar(); ?> <?php get_footer(); ?> <?php } else {?> <?php /* If this is a category archive */ if (is_category()) { ?> <h1>Posts in ‘<?php echo single_cat_title(); ?>’</h1> <?php /* If this is a daily archive */ } elseif (is_day()) { ?> <h1>Posts from <?php the_time('F jS, Y'); ?></h1> <?php /* If this is a yearly archive */ } elseif (is_year()) { ?> <h1>Posts from <?php the_time('Y'); ?></h1> <?php /* If this is an author archive */ } elseif (is_author()) { ?> <h1>Author Archive</h1> <?php /* If this is a paged archive */ } elseif (isset($_GET['paged']) && !empty($_GET['paged'])) { ?> <h1>Публикации</h1> <?php } ?> <?php if (have_posts()) : ?> <?php $post = $posts[0]; // Hack. Set $post so that the_date() works. ?> <?php while (have_posts()) : the_post(); ?> <div id="post-<?php the_ID(); ?>"> <h2><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title(); ?>"><?php the_title(); ?></a></h2> <p><?php the_time('M d') ?></p> <div> <?php the_content('read all »'); ?> </div> <div> <span><?php the_category(', ') ?></span> <span><?php comments_popup_link('0 Comments', '1 Comment', '% Comments'); ?></span> <?php edit_post_link('Edit', '«» ', ''); ?> </div> </div> <?php endwhile; ?> <div> <div><?php next_posts_link('« Previous Entries') ?></div> <div><?php previous_posts_link('Next Entries »') ?></div> </div> <?php else : ?> <h2>Not Found</h2> <?php include (TEMPLATEPATH . '/searchform.php'); ?> <?php endif; ?> </div> <?php get_sidebar(); ?> <?php get_footer(); ?> <?php } ?>
Если кому-то лень заморачиваться с правкой файлов, можно скачать архив со всеми нужными файлами. Скачать iCal.tar
15 комментариев
Красивый календарь. Такой весь айфоновский )))
Но в сентябре глючит… 10 число продублировалось и поэтому 13 сентября находится во временной анамалии )))
А так, да — тема! )))
какой браузер? Скрин не покажешь?
Все поправил, спасибо за багрепорт
Календарь в стиле iCal для архивов в wordpress…
Thank you for submitting this cool story — Trackback from progg.ru…
Ещё поправьте ссылку на скачивание. У вас http://alexvolkov.ru/wp-content/uploads/2009/09/%D0%A1%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C%20iCal.tar.gz вместо http://alexvolkov.ru/wp-content/uploads/2009/09/iCal.tar.gz
Поправил
А насколько сложно сделать из всего этого кода плагин?
Даже не знаю, не делал никогда плагины
Как-то экспериментировал с плагинами. Например, если взять код известного плагина rus-to-lat и вставить его в functions.php, то он сразу работает в данной теме оформления. Аналогично работает и russify comments. То есть таким образом можно расширить функциональность темы без необходимости дополнительной установки плагинов. Уверен, что также будут работать многие другие плагины.
А по вашему примеру можно сделать вывод, что от кода в functions.php до кода плагина один шаг 🙂
>>То есть таким образом можно расширить функциональность темы без необходимости дополнительной установки плагинов
Что я и сделал, расширил функциональность самой темы без всяких плагинов. Я вообще плагины не очень люблю и стараюст их не использовать. Всякие примочки для твитера, схожие посты, еще что-то, не помню точно, все сделано без плагинов. Поясню почему не люблю плагины:
Плагин, даже не активный, проверяется на обновления. Даже хеллоу долли. Это лишние затраты.
Выполнение плагина вклинивается между функциями ядра и выполнением темы. Т.о. это лишняя прослойка. + плагины добавляют хуки. Тоже лишнее время генерации.
Плагин — это лишний подключаемый файл. Даже если просто подключить echo «privet mir», это сожрет мин ресурс, выделенный под процесс пхп (если пхп установлен как mod_php у апача)
Из всего этого бывают случаи, когда плагины просто завешивали блог. Поэтому я стараюсь их не использовать. Да, это удобно. Но истинные рыцари джедай не ищут легких путей ))
Ну, чтобы блокировать запрос на обновления, есть плагин от Lecactus «Блокировка запросов на новые версии». Но это плагин…
На самом деле, плагин — это отличный способ расширить функциональность программы, не вникая в ее код. Это очень важно для людей, далеких от программирования. Это как раз случай WordPress, ведь большинство блоггеров не программисты.
В 6 и 7 осле не работает. Есть стили для 6 и 7?
Нет, для них нет
Уважаемый автор, вы нарисоали весьма симпатичный календарь. Есть вопрос, который меня давно мучает и ответа на него я пока найти не могу (ибо новичок): можно ли настроить календарь так, чтобы он начинался не стекущей даты (месяца), а даты давно прошедшей и настроить количество перелистываем месяцев (два-три-четыре).
Например, надо сделать навигацию по давнишним (3 года) записям относящимся к трем месяца. Календарь — очень удобный стиль отображения этого архива, но начинаться он должен естественно с даты 3-летней давности, а не с сегодняшнего числа.
думаю, у вордпресса есть возможность через параметры вызова функции задать начальную дату