Despliega un calendario en base a los parámetros mes y ańo. Muestra registros para los días en base a cualquier condición que se defina:
. Despliega calendario HTML / CSS.
. Barra de navegación opcional (adelante / atrás)
. Nombre del mes / ańo opcional.
. Posibilidad de desplegar registros.
. Para hacer el código reusable, se incluye en el ejemplo una class extendida en la cual se sobreescribe el método getHtmlContentForDay().
. getHtmlContentForDay() contiene el código que mostrará los registros para cada día, dado que cada calendario / set de datos es diferente,
es necesario implementar este método en la class base.
. Si la visibilidad de algún método está mal por favor comentar.
Implementación:
0. Un CSS (cualquier forero con paciencia puede mejorarlo).
No entra en los 10000 chars pero puedo enviarlo.
1. La class base:
Código PHP:
Ver original<?php
class Calendar {
//Url para los links en la barra de navegación, por defecto apuntan a $_SERVER['PHP_SELF']
private $url = '';
//Mes
private $month = 0;
//Ańo
private $year = 0;
//Dias en el mes
private $days_in_month = 0;
//Datos a mostrar
private $data = null;
//Links atrás / adelante
private $navigationBarPosition = false;
//Mostrar ańo mes en la barra superior
private $showDateHeader = false;
//Encabezados
public $days_headings = array ( 'Domingo',
'Lunes',
'Martes',
'Miercoles',
'Jueves',
'Viernes',
'Sabado'
);
//Constructor, nada para comentar
public function __construct($month, $year) {
// Var asignation
$this->month = $month;
$this->year = $year;
$this->days_in_month = $this->getDaysInMonth ();
$this->running_day = $this->getDayOfWeek ();
}
//Output del calendario en html
public function renderHTML() {
//init
$output = "";
//Star table
$output = '<table cellpadding="0" cellspacing="0" class="calendar">';
//Add the navigation bar
$navBarPosition = $this->getNavigationBarPosition();
if($navBarPosition == 'top' || $navBarPosition == 'both')
$output .= $this->getNavigationBarHTML();
//Add header
if($this->showDateHeader) $output .= $this->getHeaderHTML();
//First row with days names
$output .= $this->getDaysHeadingsHTML ();
//Empty day at the beginning of the month
$output .= $this->getBlankDaysHTML ();
//Rest of the days
$output .= $this->getNonBlankDaysHTML ();
//Add navigation bar
if($navBarPosition == 'bottom' || $navBarPosition == 'both')
$output .= $this->getNavigationBarHTML();
return $output;
//End
$output .="</table>";
}
protected function setUrl($value)
{
$this->url = $value;
return true;
}
//Posicion de la barra de navegación
public function setNavigationBarPosition($where) {
//Only allowed values
$allow = array('top', 'bottom', 'both'); throw new Exception ('Navigation bar position can only be top, bottom or both.');
$this->navigationBarPosition = $where;
return $this->navigationBarPosition;
}
private function setDaysHeadings
(array $names) {
$this->days_headings = $names;
return true;
}
//Muestra ańo / mes en la barra
public function setShowDateHeader($value = false)
{
$this->showDateHeader = $value;
return $this->showDateHeader;
}
public function setData($data) {
$this->data = $data;
return true;
}
//////Getters
protected function getUrl()
{
return $this->url;
}
public function getData(){
return $this->data;
}
//Dia de la semana, se utilizará para crear el HTML
protected function getDayOfWeek() {
// w Numeric representation of the day of the week 0 (for Sunday)
// through 6 (for Saturday)
return date ( 'w', mktime ( 0, 0, 0, $this->month, 1, $this->year ) ); }
protected function getDaysHeadings() {
return $this->days_headings;
}
//Cabezeras
private function getDaysHeadingsHTML() {
$output = "<tr class='calendar-row'>";
foreach ( $this->days_headings as $day_name ) {
$output .= "<td class='calendar-day-head'>{$day_name}</td>";
}
$output .= "</tr>";
return $output;
}
//Celdas vacias para los ultimos dias del mes anterior
private function getBlankDaysHTML() {
$output = "<tr>";
/* print "blank" days until the first of the current week */
for($x = 0; $x < $this->running_day; $x ++) {
$output .= "<td class='calendar-day-np'></td>";
$this->days_in_this_week ++;
}
return $output;
}
//Mostrar los registros, este método se sobreescribe desde una classe extendida
protected function getHtmlContentForDay($day_number)
{
}
//Dias con contenido
private function getNonBlankDaysHTML() {
// init
$output = "";
$day_counter = 1;
// $list_day contains the number of the day that is being displayed
for($list_day = 1; $list_day <= $this->days_in_month; $list_day ++) {
$output .= "<td class='calendar-day'>";
// add in the day number
$output .= "<div class='day-number'>{$list_day}</div>";
// The content of the day
$output .= $this->getHtmlContentForDay($list_day);
$output .= "</td>";
// End of the week, close the row
if ($this->running_day == 6) {
$output .= '</tr>';
// Go on with days
if (($day_counter) != $this->days_in_month) {
$output .= "<tr class='calendar-row'>";
}
$this->running_day = - 1;
$this->days_in_this_week = 0;
}
//Next day
$this->days_in_this_week ++;
//Actual day
$this->running_day ++;
$day_counter ++;
} // for($list_day = 1; $list_day <= $this->days_in_month; $list_day++)
//The rest of the days, after month is over, that will be printed blank
if ($this->days_in_this_week < 8) {
for($x = 1; $x <= (8 - $this->days_in_this_week); $x ++) {
$output .= "<td class='calendar-day-np'></td>";
}
}
// final row
$output .= '</tr>';
return $output;
}
//Cabecera HTML
private function getHeaderHTML()
{
//If no nav bar is going to be shown , then output this.
if(!$this->getNavigationBarPosition())
{
$header = date ( 'F', mktime ( 0, 0, 0, $this->getMonth(), 1, $this->getYear() ) ) . ', ' . $this->getYear(); $output = "<tr class='nav-bar'>";
$output .= "<td colspan='7' align='center'>{$header}</td>";
$output .= "</tr>";
return $output;
}
}
//Barra de navegación
private function getNavigationBarHTML()
{
//Get nexts and previous months and years
$next = $this->getNextMonth();
$previous = $this->getPreviousMonth();
$header = '';
//If show headers is on, put it there
if($this->getShowDateHeader())
$header = date ( 'F', mktime ( 0, 0, 0, $this->getMonth(), 1, $this->getYear() ) ) . ', ' . $this->getYear();
$output = "<tr class='nav-bar'><td align='center'><a href='{$this->getUrl()}?calendar_year={$previous['year']}&calendar_month={$previous['month']}'>Previous</a></td>";
$output .= "<td colspan='5' align='center'>{$header}</td>";
$output .= "<td align='center'><a href='{$this->getUrl()}?calendar_year={$next['year']}&calendar_month={$next['month']}''>Next</a></td></tr>";
return $output;
}
private function getNavigationBarPosition()
{
return $this->navigationBarPosition;
}
private function getShowDateHeader()
{
return $this->showDateHeader;
}
protected function getMonth() {
return $this->month;
}
protected function getYear()
{
return $this->year;
}
//Ańos y meses anteriores y posteriores
private function getNextMonth() {
//Get next month
$month = $this->getMonth() + 1;
$year = $this->getYear();
if($month < 1)
{
$month = 12;
$year--;
}
if($month >= 13)
{
$month = 1;
$year++;
}
if($month < 10) $month = '0' . $month;
return array('month' => $month, 'year' => $year); }
private function getPreviousMonth() {
//Get next month
$month = $this->getMonth() - 1;
$year = $this->getYear();
if($month < 1)
{
$month = 12;
$year--;
}
if($month >= 13)
{
$month = 1;
$year++;
}
if($month < 10) $month = '0' . $month;
return array('month' => $month, 'year' => $year); }
//Dias del mes
private function getDaysInMonth() {
return date ( 't', mktime ( 0, 0, 0, $this->month, 1, $this->year ) ); }
}
?>
2. Una clase extendida
Código PHP:
Ver original<?php
class MyCalendar Extends Calendar
{
/**
* Este es el único método que en principio debe extenderse.
* La razón es que cada calendario particular mostrará registros
* en base a distintos criterio.
* @see Calendar::getHtmlContentForDay()
*/
public function getHtmlContentForDay($day_number)
{
//En mi ejemplo, los registros tienen un campo date que uso para saber si debo mostrar el registro o no
//Inicializar variables
$output = '';
foreach($this->getData() as $index => $values)
{
//Si el dia de inicio es igual a $day_number, muestro el registro con un link
if($values['date'] == $this->getYear() .'-'. $this->getMonth() .'-'. $day_number)
{
$output .= "<a href='#'>[{$index}] ".substr($values['note'], 0, 10)."...</a><br>"; }
}
return $output;
}
}
?>
3. Un script de ejemplo
Código PHP:
Ver original<link rel="stylesheet" media="all" href="style.css">
<?php
//Incluir classes
include 'class.Calendar.php';
include 'class.MyCalendar.php';
//Datos de prueba
0 => array('id' => 3434, 'date' => '2013-06-24', 'note' => 'Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..'), 1 => array('id' => 4532, 'date' => '2013-06-25', 'note' => 'Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..'), 2 => array('id' => 3355, 'date' => '2013-06-28', 'note' => 'Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..'), 3 => array('id' => 9876, 'date' => '2013-06-28', 'note' => 'Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..');
//Mes y ańo, si no vienen por get, utilizo los actuales
$month = isset ( $_GET ['calendar_month'] ) ?
$_GET ['calendar_month'] : date ( 'm' ); $year = isset ( $_GET ['calendar_year'] ) ?
$_GET ['calendar_year'] : date ( 'Y' ); //Inicializar objeto
$cal = new MyCalendar ( $month, $year );
//Con barra de navegación arriba
$cal->setNavigationBarPosition ( 'top' );
//Mostrar el mes y el ańo
$cal->setShowDateHeader ( true );
//Pasar los datos a mostrar
$cal->setData($data);
$out = $cal->renderHTML ();
echo $out;
?>
Saludos y espero que a alguien le sirva,
[email protected]