BLOG DE DISEÑO WEB CORUÑA

Un poco de todo, recursos, tutoriales, noticias, anuncios...

Calendario de eventos en PHP, Ajax, jQuery y ventanas modales

01/FEB/2013 27.594 visitas Ver comentarios
Calendario de eventos en PHP, Ajax, jQuery y ventanas modales

ADVERTENCIA: Este artículo tiene más de 6 meses de antigüedad. Puede que esta información ya se encuentre obsoleta o haya nuevas y mejores opciones.

ACTUALIZACIÓN AGOSTO 2013. A pedido de una usuaria (en los comentarios se ve), he realizado una pequeña modificación para que el calendario soporte la edición de eventos. Si quieres descargar el código con edición de eventos, pulsa este enlace. Recuerda que el código aquí pegado y el que te descargas desde el botón azul, no contienen la edición de eventos.

Si ya conocías el antiguo calendario multieventos en PHP y te gustaba, lo que te dejo ahora te debería gustar aún más. Viendo que muchos comentarios me pedían funcionalidades para el antiguo calendario y, empujado, por la necesidad de hacer un calendario que no refrescara la página con el cambio de mes, he reescrito el código para modernizarlo.

Este nuevo calendario, que puedes ver la demo online haciendo click en el botón superior, es multieventos, pero para no ensuciar la tabla del mes, mostrará como enlace los días en los que existas eventos, abriendo una modal window o ventana modal para la gestión de esos eventos.

También, permitirá agregar cuantos eventos quieras a un día pero sólo al día actual y próximos, pero permitir eventos en días pasados es tan sencillo como comentar una línea.

El proceso
Consta de 3 partes que son un PHP inicial con el código javascript necesario para las llamadas AJAX... un PHP "oculto" que se encargará de ejecutar las funciones que nuestro javascript le ordene y por último un poquito de CSS para mantener la forma del calendario original.

El código
No es más que lo que ves. Hay una tabla MySQL que tiene un campo ID, otro FECHA (en date) y otro de EVENTO (un varchar) y un archivo de conexión a la base de datos. Pero como me vas a decir... ehh quiero descargarlo, pues eso, ahí lo tienes.

El funcionamiento
Cada día del mes elegido mostrará un link cuando contenga eventos. Los eventos se consultan una única vez por mes en la base de datos al cargar el calendario. Cada inserción o eliminación que haces procesa automáticamente el cambio en la base de datos pero el calendario se regenerará sólamente cuando cierres el modal.

Archivos faltantes
Si te bajas el .zip habrá un config.inc.php que debes rellenar y el .SQL exportado de la tabla. Si usabas el calendario anterior, la base de datos es la misma.

Que lo disfrutes!

Código 1 - PHP
<?php
error_reporting(-1);
require_once("config.inc.php");
?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1" />
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
<title>Calendario en PHP, AJAX y jQuery con eventos</title>
<meta http-equiv="PRAGMA" content="NO-CACHE" />
<meta http-equiv="EXPIRES" content="-1" />
<script src="http://code.jquery.com/jquery-1.9.0.min.js"></script>
<link type="text/css" rel="stylesheet" media="all" href="estilos.css" />
<script type="text/javascript">
function generar_calendario(mes,anio)
{
var agenda=$("#agenda");
agenda.html("<img src='images/loading.gif'>");
$.ajax({
type: "GET",
url: "ajax_calendario.php",
cache: false,
data: { mes:mes,anio:anio,accion:"generar_calendario" }
}).done(function( respuesta )
{
agenda.html(respuesta);
$('a.modal').bind("click",function(e)
{
e.preventDefault();
var id = $(this).data('evento');
var fecha = $(this).attr('rel');
if (fecha!="")
{
$("#evento_fecha").val(fecha);
$("#que_dia").html(fecha);
}
var maskHeight = $(document).height();
var maskWidth = $(window).width();
$('#mask').css({'width':maskWidth,'height':maskHeight});
$('#mask').fadeIn(1000);
$('#mask').fadeTo("slow",0.8);
var winH = $(window).height();
var winW = $(window).width();
$(id).css('top', winH/2-$(id).height()/2);
$(id).css('left', winW/2-$(id).width()/2);
$(id).fadeIn(200);
});
$('.close').bind("click",function (e)
{
var fecha=$(this).attr("rel");
var nueva_fecha=fecha.split("-");
e.preventDefault();
$('#mask').hide();
$('.window').hide();
generar_calendario(nueva_fecha[1],nueva_fecha[0]);
});
//guardar evento
$('.enviar').bind("click",function (e)
{
e.preventDefault();
$("#respuesta_form").html("<img src='images/loading.gif'>");
var evento=$("#evento_titulo").val();
var fecha=$("#evento_fecha").val();
$.ajax({
type: "GET",
url: "ajax_calendario.php",
cache: false,
data: { evento:evento,fecha:fecha,accion:"guardar_evento" }
}).done(function( respuesta2 )
{
$("#respuesta_form").html(respuesta2);
var evento=$("#evento_titulo").val("");
});
});
//eliminar evento
$('.eliminar_evento').bind("click",function (e)
{
e.preventDefault();
var current_p=$(this);
$(".respuesta").html("<img src='images/loading.gif'>");
var id=$(this).attr("rel");
$.ajax({
type: "GET",
url: "ajax_calendario.php",
cache: false,
data: { id:id,accion:"borrar_evento" }
}).done(function( respuesta2 )
{
$(".respuesta").html(respuesta2);
current_p.parent("p").fadeOut();
});
});
$(".anterior,.siguiente").bind("click",function(e)
{
e.preventDefault();
var datos=$(this).attr("rel");
var nueva_fecha=datos.split("-");
generar_calendario(nueva_fecha[1],nueva_fecha[0]);
})
$(window).resize(function ()
{
var box = $('#boxes .window');
var maskHeight = $(document).height();
var maskWidth = $(window).width();
$('#mask').css({'width':maskWidth,'height':maskHeight});
var winH = $(window).height();
var winW = $(window).width();
box.css('top', winH/2 - box.height()/2);
box.css('left', winW/2 - box.width()/2);
});
});
}
$(document).ready(function()
{
/* GENERAMOS CALENDARIO CON FECHA DE HOY */
generar_calendario("<?php if (isset($_GET["mes"])) echo $_GET["mes"]; ?>","<?php if (isset($_GET["anio"])) echo $_GET["anio"]; ?>");
setTimeout(function() {$('#mensaje').fadeOut('fast');}, 3000);
});
</script>
</head>
<body>
<div id="agenda"></div>
<div id="mask"></div>
<!-- ESTO NO TE HACE FALTA! -->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("<script src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'></script>"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-266167-20");
pageTracker._setDomainName(".martiniglesias.eu");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>
Código 2 - PHP
<?php
error_reporting(-1);
require_once("config.inc.php");
function fecha ($valor)
{
$timer = explode(" ",$valor);
$fecha = explode("-",$timer[0]);
$fechex = $fecha[2]."/".$fecha[1]."/".$fecha[0];
return $fechex;
}
function buscar_en_array($fecha,$array)
{
$total_eventos=count($array);
for($e=0;$e<$total_eventos;$e++)
{
if ($array[$e]["fecha"]==$fecha) return true;
}
}
switch ($_GET["accion"])
{
case "guardar_evento":
{
$query="insert into tcalendario (fecha,evento) values ('".$_GET["fecha"]."','".strip_tags($_GET["evento"])."')";
mysql_select_db($dbname);
if ($resultado=mysql_query($query)) echo "<p class='ok'>Evento guardado correctamente.</p>";
else echo "<p class='error'>Se ha producido un error guardando el evento.</p>";
break;
}
case "borrar_evento":
{
$query="delete from tcalendario where id='".$_GET["id"]."' limit 1";
mysql_select_db($dbname);
if ($resultado=mysql_query($query)) echo "<p class='ok'>Evento eliminado correctamente.</p>";
else echo "<p class='error'>Se ha producido un error eliminando el evento.</p>";
break;
}
case "generar_calendario":
{
$fecha_calendario=array();
if ($_GET["mes"]=="" || $_GET["anio"]=="")
{
$fecha_calendario[1]=intval(date("m"));
if ($fecha_calendario[1]<10) $fecha_calendario[1]="0".$fecha_calendario[1];
$fecha_calendario[0]=date("Y");
}
else
{
$fecha_calendario[1]=intval($_GET["mes"]);
if ($fecha_calendario[1]<10) $fecha_calendario[1]="0".$fecha_calendario[1];
else $fecha_calendario[1]=$fecha_calendario[1];
$fecha_calendario[0]=$_GET["anio"];
}
$fecha_calendario[2]="01";
/* obtenemos el dia de la semana del 1 del mes actual */
$primeromes=date("N",mktime(0,0,0,$fecha_calendario[1],1,$fecha_calendario[0]));
/* comprobamos si el año es bisiesto y creamos array de días */
if (($fecha_calendario[0] % 4 == 0) && (($fecha_calendario[0] % 100 != 0) || ($fecha_calendario[0] % 400 == 0))) $dias=array("","31","29","31","30","31","30","31","31","30","31","30","31");
else $dias=array("","31","28","31","30","31","30","31","31","30","31","30","31");
$eventos=array();
$query="select * from tcalendario where month(fecha)='".$fecha_calendario[1]."' and year(fecha)='".$fecha_calendario[0]."'";
mysql_select_db($dbname);
$resultado=mysql_query($query);
if ($fila=mysql_fetch_array($resultado))
{
$posicion=0;
do
{
$eventos[$posicion]["id"]=$fila["id"];
$eventos[$posicion]["fecha"]=$fila["fecha"];
$eventos[$posicion]["evento"]=$fila["evento"];
$posicion+=1;
}
while($fila=mysql_fetch_array($resultado));
}
$meses=array("","Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre");
/* calculamos los días de la semana anterior al día 1 del mes en curso */
$diasantes=$primeromes-1;
/* los días totales de la tabla siempre serán máximo 42 (7 días x 6 filas máximo) */
$diasdespues=42;
/* calculamos las filas de la tabla */
$tope=$dias[intval($fecha_calendario[1])]+$diasantes;
if ($tope%7!=0) $totalfilas=intval(($tope/7)+1);
else $totalfilas=intval(($tope/7));
/* empezamos a pintar la tabla */
echo "<h2>Calendario de Eventos para: ".$meses[intval($fecha_calendario[1])]." de ".$fecha_calendario[0]."</h2>";
if (isset($mostrar)) echo $mostrar;
echo "<table class='calendario' cellspacing='0' cellpadding='0'>";
echo "<tr><th>Lunes</th><th>Martes</th><th>Miércoles</th><th>Jueves</th><th>Viernes</th><th>Sábado</th><th>Domingo</th></tr><tr>";
/* inicializamos filas de la tabla */
$tr=0;
$dia=1;
for ($i=1;$i<=$diasdespues;$i++)
{
if ($tr<$totalfilas)
{
if ($i>=$primeromes && $i<=$tope)
{
echo "<td class='";
/* creamos fecha completa */
if ($dia<10) $dia_actual="0".$dia; else $dia_actual=$dia;
$fecha_completa=$fecha_calendario[0]."-".$fecha_calendario[1]."-".$dia_actual;
if (count($eventos)>0 && buscar_en_array($fecha_completa,$eventos)==true) echo "evento";
/* si es hoy coloreamos la celda */
if (date("Y-m-d")==$fecha_completa) echo " hoy";
echo "'>";
/* recorremos el array de eventos para mostrar los eventos del día de hoy */
$total_eventos=count($eventos);
$eventos_del_dia="";
for($e=0;$e<$total_eventos;$e++)
{
if ($eventos[$e]["fecha"]==$fecha_completa)
{
$eventos_del_dia.="<p>".$eventos[$e]["evento"]."<a href='#' class='eliminar_evento' rel='".$eventos[$e]["id"]."' title='Eliminar este Evento del ".fecha($fecha_completa)."'><img src='images/delete.png' /></a></p>";
}
}
if ($eventos_del_dia!="")
{
echo "<a href='#' data-evento='#evento".$dia_actual."' class='modal' rel='".$fecha_completa."'>".$dia."</a><div class='window' id='evento".$dia_actual."'>";
echo "<h2>Eventos del ".fecha($fecha_completa)."</h2><a href='#' class='close' rel='".$fecha_completa."'>Cerrar</a><div class='respuesta'></div>";
echo $eventos_del_dia;
echo "</div>";
}
else echo "$dia";
/* agregamos enlace a nuevo evento si la fecha no ha pasado */
if (date("Y-m-d")<=$fecha_completa) echo "<a href='#' data-evento='#nuevo_evento' title='Agregar un Evento el ".fecha($fecha_completa)."' class='modal agregar_evento' rel='".$fecha_completa."'><img src='images/add.png' /></a>";
echo "</td>";
$dia+=1;
}
else echo "<td class='desactivada'> </td>";
if ($i==7 || $i==14 || $i==21 || $i==28 || $i==35 || $i==42) {echo "<tr>";$tr+=1;}
}
}
echo "</table>";
echo "<div id='nuevo_evento' class='window'>";
echo "<h2>Agregar un evento el <span id='que_dia'></span></h2><a href='#' class='close' rel='".$fecha_completa."'>Cerrar</a><div id='respuesta_form'></div>";
echo "<form><input type='text' name='evento_titulo' id='evento_titulo'><input type='button' name='Enviar' value='Guardar' class='enviar'><input type='hidden' name='evento_fecha' id='evento_fecha'></form>";
			echo "</div>";
			
			$mesanterior=date("Y-m-d",mktime(0,0,0,$fecha_calendario[1]-1,01,$fecha_calendario[0]));
			$messiguiente=date("Y-m-d",mktime(0,0,0,$fecha_calendario[1]+1,01,$fecha_calendario[0]));
			echo "<p>« <a href='#' rel='$mesanterior' class='anterior'>Mes Anterior</a> - <a href='#' class='siguiente' rel='$messiguiente'>Mes Siguiente</a> »</p>";
		break;
	}
}
?>
Código 3 - CSS
* {margin: 0;padding: 0;font-family:Helvetica, Arial, Tahoma, sans-serif;}
img{border:0}
html,body{height:100%;width:100%;outline:0;overflow:hidden}
body {text-align:center;margin:0;width:100%;height:100%;overflow:hidden;background:#fff;padding:30px 0}

#agenda{margin:10px;width:980px;margin:0 auto}
#agenda h1{text-align:left;margin:0;font-size:1.5em;color:#312c2b}
#agenda h2{text-align:left;margin:0;font-size:1em;color:#969696}

#agenda table.calendario {margin:10px auto;width:100%;border:1px dotted #ccc;}

.calendario th {border:1px dotted #ccc;font-weight:bold;background:#666;color:white;padding:10px;font-size:12px;}
.calendario td{padding:10px;text-align:center;border:1px dotted #ccc;width:100px;white-space:pre-line;font-size:24px;}
	
	.calendario td.evento {background:#f2f2f2;}
	.calendario td.desactivada {background:#f6f6f6;}
	.calendario td.hoy{font-weight:bold}
	a.agregar_evento{position:relative;margin-left:25px;margin-top:-25px}
	.calendario td a{color:red;text-decoration:none;}

.verde,.ok{font-weight:bold;color:green;}
.rojo{font-size:125% !important;font-weight:bold;color:red;}
.siguiente,.anterior{color:red;text-decoration:none}

#mask {position:absolute;left:0;top:0;z-index:9000;background-color:#000;display:none;width:100%;height:100%}

#respuesta_form,.respuesta{clear:both;padding:20px 0;}
  
.window {position:fixed;left:0;top:0;width:440px;height:400px;display:none;z-index:9999;padding:20px;background-color:#ffffff;}

	.window h2{float:left;padding:0 0 20px 0;text-align:left;margin:0;font-size:1em;color:#969696}
	.window a.close{float:right;font-size:11px !important}
	.window p{margin:5px 0;font-size:12px;border:1px solid #ccc;text-align:left;padding:5px;clear:both;}
	
	.window form{padding:20px 0 !important;clear:both}
	.window input[type=text]{border:1px dotted #ccc;background:white;width:200px;padding:10px}
	.window input.enviar{border:1px dotted #ccc;background:white;width:120px;background:#ccc;margin:0 0 0 10px;padding:10px}
	.window p img{vertical-align:middle;float:right;border:0;width:16px;height:16px}

Acerca del Autor...

Macadia, es una agencia de Diseño Web Coruña, especializada en maquetación css y desarrollo de páginas web a medida con más de 21 años de experiencia en el desarrollo de páginas web profesionales. Si te ha gustado este artículo, por favor, ayúdanos a difundirlo compartiéndolo con tus amigos y contactos en las distintas redes sociales que utilices. ¡Muchas gracias!

Los comentarios han sido desactivados momentaneamente a la espera de que Disqus adapte su plataforma a la próxima RGPD que entra en vigor desde el 25/05/2018