Yii: Добавляем календарь материалов

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

Недавно мы уже сделали архив статей по месяцам. Добавим теперь такую популярную полезность - календарь на Yii. Это тоже добавляет удобства в ориентировании на сайте.

Сначала добавляем вызов виджета в /protected/views/layouts/column3.php

<?php $this->widget('Calendar'); ?>

В компонентах создаём файл для календаря - /protected/components/Calendar.php  с содержимым:

 

<?php

class Calendar extends CWidget
{
  public $title='Calendar';

  public function run()
  {
    // Set locale
    if (isset(Yii::app()->params['calendarLocale']) && Yii::app()->params['calendarLocale'] == 'Japan') {
      $locale='ja_JP.utf8';
      $setlocale = setlocale(LC_ALL, $locale);
    }

    // Prepare the css style within the calendar widget
    $url=CHtml::asset(Yii::getPathOfAlias('application.components.css.calendar').'.css');
    Yii::app()->getClientScript()->registerCssFile($url);

    // Previous month and next month
    if (!empty($_GET['time'])) {
      $month = date('n', $_GET['time']);
      $year = date('Y', $_GET['time']);
      if (!empty($_GET['pnc']) && $_GET['pnc'] == 'n') $month++;
      if (!empty($_GET['pnc']) && $_GET['pnc'] == 'p') $month--;
    } else {
      $month = date('n');
      $year = date('Y');
    }

    $firstDay = mktime(0,0,0,$month,1,$year);
    $firstDayNextMonth = mktime(0,0,0,$month+1,1,$year);

    $pnc = array('&lt;'=>CHtml::normalizeUrl(array('material/PostedInMonth', 'time'=>$firstDay, 'pnc'=>'p')),
                 '&gt;'=>CHtml::normalizeUrl(array('material/PostedInMonth', 'time'=>$firstDay, 'pnc'=>'n')));

    // Today
    $days = array();
    if ($firstDay <= time() && time() < $firstDayNextMonth) {
      $today = date('j', time());
      $days[$today] = array(NULL,NULL,'<span id="today">'.$today.'</span>');
    }

    // Make the links
    $material = new Material;
    foreach($material->findMaterialPostedThisMonth() as $article) {
      $days[date('j', strtotime($article->create_time))] = array(CHtml::normalizeUrl(array('material/PostedOnDate', 'time'=>strtotime($article->create_time))), 'linked-day');
    }

    if (isset($locale) && $locale == 'ja_JP.utf8') $len = 3;
    else $len = 2;
               
    $this->render('calendar', array('year'=>$year, 'month'=>$month, 'days'=>$days, 'len'=>$len, 'url'=>'', 'pnc'=>$pnc));
  }

}

А также в видах компонентов создаём - /protected/components/views/calendar.php

 

<div id="harrisNewsHeader">
    <div id="HarrisNews" class="portlet-comments">
        <h3>Календарь</h3>
<center>
<ul class="Calendar">
<?php
   if (isset(Yii::app()->params['calendarLocale']) && Yii::app()->params['calendarLocale'] == 'Japan')
     include_once('generate_calendar_Japan.php');
   else
     include_once('generate_calendar.php');
echo generate_calendar($year, $month, $days, $len, $url, 0, $pnc);
?>
</ul>
</center>
</div>
<div id="HarrisNewsFooter"></div>
</div>

И /protected/components/views/generate_calendar.php

<?php
# PHP Calendar (version 2.3), written by Keith Devens
# http://keithdevens.com/software/php_calendar
#  see example at http://keithdevens.com/weblog
# License: http://keithdevens.com/software/license

function generate_calendar($year, $month, $days = array(), $day_name_length = 3, $month_href = NULL, $first_day = 0, $pn = array()){
        $first_of_month = gmmktime(0,0,0,$month,1,$year);
        #remember that mktime will automatically correct if invalid dates are entered
        # for instance, mktime(0,0,0,12,32,1997) will be the date for Jan 1, 1998
        # this provides a built in "rounding" feature to generate_calendar()

        $day_names = array(); #generate all the day names according to the current locale
        for($n=0,$t=(3+$first_day)*86400; $n<7; $n++,$t+=86400) #January 4, 1970 was a Sunday
                $day_names[$n] = ucfirst(gmstrftime('%A',$t)); #%A means full textual day name

        list($month, $year, $month_name, $weekday) = explode(',',gmstrftime('%m,%Y,%B,%w',$first_of_month));
        $weekday = ($weekday + 7 - $first_day) % 7; #adjust for $first_day
        $title   = htmlentities(ucfirst($month_name)).'&nbsp;'.$year;  #note that some locales don't capitalize month and day names

        #Begin calendar. Uses a real <caption>. See http://diveintomark.org/archives/2002/07/03
        @list($p, $pl) = each($pn); @list($n, $nl) = each($pn); #previous and next links, if applicable
        if($p) $p = '<span class="calendar-prev">'.($pl ? '<a href="'.htmlspecialchars($pl).'">'.$p.'</a>' : $p).'</span>&nbsp;';
        if($n) $n = '&nbsp;<span class="calendar-next">'.($nl ? '<a href="'.htmlspecialchars($nl).'">'.$n.'</a>' : $n).'</span>';
        $calendar = '<table>'."\n".
                '<div class="calendar-month">'.$p.($month_href ? '<a href="'.htmlspecialchars($month_href).'">'.$title.'</a>' : $title).$n."</div>\n<tr>";

        if($day_name_length){ #if the day names should be shown ($day_name_length > 0)
                #if day_name_length is >3, the full name of the day will be printed
                foreach($day_names as $d)
                        $calendar .= '<th abbr="'.htmlentities($d).'">'.htmlentities($day_name_length < 4 ? substr($d,0,$day_name_length) : $d).'</th>';
                $calendar .= "</tr>\n<tr>";
        }

        if($weekday > 0) $calendar .= '<td colspan="'.$weekday.'">&nbsp;</td>'; #initial 'empty' days
        for($day=1,$days_in_month=gmdate('t',$first_of_month); $day<=$days_in_month; $day++,$weekday++){
                if($weekday == 7){
                        $weekday   = 0; #start a new week
                        $calendar .= "</tr>\n<tr>";
                }
                if(isset($days[$day]) and is_array($days[$day])){
                        @list($link, $classes, $content) = $days[$day];
                        if(is_null($content))  $content  = $day;
                        $calendar .= '<td'.($classes ? ' class="'.htmlspecialchars($classes).'">' : '>').
                                ($link ? '<a href="'.htmlspecialchars($link).'">'.$content.'</a>' : $content).'</td>';
                }
                else $calendar .= "<td>$day</td>";
        }
        if($weekday != 7) $calendar .= '<td colspan="'.(7-$weekday).'">&nbsp;</td>'; #remaining "empty" days

        return $calendar."</tr>\n</table>\n";
}
?>

И ещё нужны стили /protected/components/css/calendar.css

 

/**
 * CSS styles for Calendar
 */
ul.Calendar
{
        font-size:11px;
#       border:0;
#       line-height:150%;
        display:inline;
}

ul.Calendar li
{
        display:inline;
}

ul.Calendar a:link,
ul.Calendar a:visited
{
        border:solid 1px #c3881a;
        color:#801000;
        padding:1px 3px;
        text-decoration:none;
}

ul.Calendar .page a
{
        font-weight:normal;
}

ul.Calendar a:hover
{
        border:solid 1px #801000;
}

ul.Calendar #today
{
        color:#990000;
        font-weight: bold;
}

ul.Calendar table
{
        margin-bottom: 0px;
        width: 87%;
}

ul.Calendar th,
ul.Calendar td,
ul.Calendar caption
{
        text-align: center;
        padding: 2px 0px;
}

ul.Calendar .calendar-month
{
        padding: 5px 0px;
        text-align: center;
}

Теперь всё.

 

 

 

Источник: loco.ru

almix
Разработчик Loco, автор статей по веб-разработке на Yii, CodeIgniter, MODx и прочих инструментах. Создатель Team Sense.

Вы можете почитать все статьи от almix'а.



Другие статьи по этой теме:

Комментарии (3)     Подпишитесь на RSS комментариев к этой статье.

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

#322
Мастер говорит:
March 12, 2012 at 08:08 pm
findMaterialPostedThisMonth что это за функция, откуда она?

#323
Саша Loco говорит:
March 12, 2012 at 11:31 pm

вот эта хренова функция, она в модели Материалов (статей) находится:

/**
             * Находит материалы,опубликованные в этом месяце
             * @возвращает массив материалов этого месяца
             */
            public function findMaterialPostedThisMonth()
            {
                    if (!empty($_GET['time'])) {
                            $month = date('n', $_GET['time']);
                            $year = date('Y', $_GET['time']);
                            if (!empty($_GET['pnc']) && $_GET['pnc'] == 'n') $month++;
                            if (!empty($_GET['pnc']) && $_GET['pnc'] == 'p') $month--;
                    } else {
                            $month = date('n');
                            $year = date('Y');
                    }

                    return $this->findAll(array(
                            'condition'=>'create_time > :time1 AND create_time < :time2
                                            AND t.status='.self::STATUS_PUBLISHED,
                            'params'=>array(':time1' => date("Y-m-d", mktime(0,0,0,$month,1,$year)),
                                            ':time2' => date("Y-m-d", mktime(0,0,0,$month+1,1,$year)),
                                    ),
                            'order'=>'t.create_time DESC',
                    ));
            }


#498
nmdimas говорит:
June 10, 2012 at 04:06 pm

А зачем при переключении месяца сразу же перезагружается страница с результатом?

Логично было бы если например сегодня 1 число просмотреть что было в прошлом месяце 31 . то есть надо сначала клацнуть назад страница перезагружается потом нажать на 31.