Calendario de eventos - Carga y eliminación de eventos predefinidos

Desde la página 'index.php' podemos acceder a la página que permite agregar y borrar eventos predefinidos mediante el botón 'Administrar eventos predefinidos'.

La interfaz visual de la página 'eventospredefinidos.html' es:

Calendario de eventos php

El código completo de la página es:

eventospredefinidos.html
<!DOCTYPE html>
<html lang="es">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Calendario de Eventos</title>

  <link href="bootstrap-4.3.1/css/bootstrap.min.css" rel="stylesheet">
  <link href="datatables/datatables.min.css" rel="stylesheet">
  <link href="clockpicker/bootstrap-clockpicker.css" rel="stylesheet">

  <script src="js/jquery-3.4.1.js"></script>
  <script src="js/popper.min.js"></script>
  <script src="bootstrap-4.3.1/js/bootstrap.min.js"></script>
  <script src="datatables/datatables.min.js"></script>
  <script src="clockpicker/bootstrap-clockpicker.js"></script>
  <script src='js/moment-with-locales.js'></script>
</head>

<body>
  <div class="container">
    <div class="row">
      <div class="col-12">
        <h2 style="text-align:center">Administración de eventos predefinidos</h2>
        <table class="table table-striped table-bordered table-hover" id="tabla1">
          <thead>
            <tr>
              <td>Evento</td>
              <td>titulo</td>
              <td>Color de<br>texto</td>
              <td>Color de<br> fondo</td>
              <td>Hora de<br>inicio</td>
              <td>Hora de<br>fin</td>
              <td>Borrar</td>
            </tr>
          </thead>
        </table>

        <!-- FormularioEventosPredefinidos -->
        <div class="modal fade" id="FormularioEventosPredefinidos" tabindex="-1" role="dialog">
          <div class="modal-dialog" role="document">
            <div class="modal-content">
              <div class="modal-header">

                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                  <span aria-hidden="true">×</span>
                </button>
              </div>
              <div class="modal-body">
                <div class="form-row">
                  <div class="form-group col-md-12">
                    <label>Evento predefinido:</label>
                    <input type="text" id="Titulo" name="Titulo" class="form-control" placeholder="">
                  </div>
                </div>

                <div class="form-group">
                  <label>Color de fondo:</label>
                  <input type="color" value="#3788D8" id="ColorFondo" class="form-control" style="height:36px;">
                </div>
                <div class="form-group">
                  <label>Color de texto:</label>
                  <input type="color" value="#ffffff" id="ColorTexto" class="form-control" style="height:36px;">
                </div>

                <div class="form-group">
                  <label>Hora de inicio:</label>

                  <div class="input-group clockpicker" data-autoclose="true">
                    <input type="text" id="HoraInicio" value="" class="form-control" autocomplete="off" />
                  </div>
                </div>
                <div class="form-group">
                  <label>Hora de fin:</label>

                  <div class="input-group clockpicker" data-autoclose="true">
                    <input type="text" id="HoraFin" value="" class="form-control" autocomplete="off" />
                  </div>
                </div>
              </div>
              <div class="modal-footer">

                <button type="submit" id="BotonConfirmarAgregar" class="btn btn-success">Confirmar</button>
                <button type="button" class="btn btn-success" data-dismiss="modal">Cancelar</button>

              </div>
            </div>
          </div>
        </div>

        <div><button type="button" id="BotonAgregar" class="btn btn-success">Agregar evento predefinido</button></div>
        <hr>
        <div style="text-align:center"><button type="button" id="BotonSalir" class="btn btn-success">Retornar al
            calendario</button>
        </div>

      </div>
    </div>
  </div>

  <script>


    document.addEventListener('DOMContentLoaded', function () {

      $('.clockpicker').clockpicker();

      let tabla1 = $('#tabla1').DataTable({
        "ajax": {
          url: 'datoseventospredefinidos.php?accion=listar',
          dataSrc: ""
        },
        "columns": [{
          "data": "codigo"
        },
        {
          "data": "titulo"
        },
        {
          "data": "colortexto"
        },
        {
          "data": "colorfondo"
        },
        {
          "data": "horainicio"
        },
        {
          "data": "horafin"
        },
        {
          "data": null,
          "orderable": false
        }
        ],
        columnDefs: [{
          targets: -1,
          className: 'dt-body-center',
          "defaultContent": "<button class='btn btn-sm btn-danger botonborrar'>Borra?</button>",
          data: null
        }, {
          targets: 1,
          className: 'dt-body-center'
        },
        {
          targets: 2,
          className: 'dt-body-center'
        }
        ],
        'rowCallback': function (row, data, index) {
          $(row).find('td:eq(1)').css('color', data.colortexto);
          $(row).find('td:eq(1)').css('background-color', data.colorfondo);
        },
        "language": {
          "url": "datatables/spanish.json",
        },
        "lengthMenu": [
          [10, 25, 50, -1],
          [10, 25, 50, "Todos"]
        ],
      });


      $('#tabla1 tbody').on('click', 'button.botonborrar', function () {
        if (confirm("Realmente quiere borrar el evento predefinido?")) {
          let registro = tabla1.row($(this).parents('tr')).data();
          borrarRegistro(registro);
        }
      });


      //Eventos de botones de la aplicación
      $('#BotonAgregar').click(function () {
        limpiarFormulario();
        $("#FormularioEventosPredefinidos").modal();
      });

      $('#BotonConfirmarAgregar').click(function () {
        let registro = recuperarDatosFormulario();
        agregarRegistro(registro);
        $("#FormularioEventosPredefinidos").modal('hide');
      });

      $('#BotonSalir').click(function () {
        window.location = "index.php";
      });

      // funciones para comunicarse con el servidor via ajax
      function agregarRegistro(registro) {
        $.ajax({
          type: 'POST',
          url: 'datoseventospredefinidos.php?accion=agregar',
          data: registro,
          success: function (msg) {
            tabla1.ajax.reload();
          },
          error: function (error) {
            alert("Hay un problema:" + error);
          }
        });
      }

      function borrarRegistro(registro) {
        $.ajax({
          type: 'POST',
          url: 'datoseventospredefinidos.php?accion=borrar',
          data: registro,
          success: function (msg) {
            tabla1.ajax.reload();
          },
          error: function (error) {
            alert("Hay un problema:" + error);
          }
        });
      }


      // funciones que interactuan con el formulario de entrada de datos
      function limpiarFormulario() {
        $('#Titulo').val('');
        $('#HoraInicio').val('');
        $('#HoraFin').val('');
        $('#ColorFondo').val('#3788D8');
        $('#ColorTexto').val('#ffffff');

      }

      function recuperarDatosFormulario() {
        let registro = {
          titulo: $('#Titulo').val(),
          horainicio: $('#HoraInicio').val(),
          horafin: $('#HoraFin').val(),
          colorfondo: $('#ColorFondo').val(),
          colortexto: $('#ColorTexto').val()
        };
        return registro;
      }


    });
  </script>

</body>

</html>
Lo primero que hacemos es importar tanto el archivo js como css del plug-in DataTables (solo recordar que la librería JQuery debe importarse primero):

  <link href="bootstrap-4.3.1/css/bootstrap.min.css" rel="stylesheet">
  <link href="datatables/datatables.min.css" rel="stylesheet">
  <link href="clockpicker/bootstrap-clockpicker.css" rel="stylesheet">

  <script src="js/jquery-3.4.1.js"></script>
  <script src="js/popper.min.js"></script>
  <script src="bootstrap-4.3.1/js/bootstrap.min.js"></script>
  <script src="datatables/datatables.min.js"></script>
  <script src="clockpicker/bootstrap-clockpicker.js"></script>
  <script src='js/moment-with-locales.js'></script>

Creamos una tabla HTML donde luego en forma dinámica el plug-in DataTables se encargará de agregar todas sus filas que serán recuperadas del servidor:

<table class="table table-striped table-bordered table-hover" id="tabla1">
          <thead>
            <tr>
              <td>Evento</td>
              <td>titulo</td>
              <td>Color de<br>texto</td>
              <td>Color de<br> fondo</td>
              <td>Hora de<br>inicio</td>
              <td>Hora de<br>fin</td>
              <td>Borrar</td>
            </tr>
          </thead>
        </table>

Creamos ahora un objeto de la clase 'DataTables' y le pasamos un objeto iniciando distintas propiedades que configurarán la tabla:

      let tabla1 = $('#tabla1').DataTable({
        "ajax": {
          url: 'datoseventospredefinidos.php?accion=listar',
          dataSrc: ""
        },
        "columns": [{
          "data": "codigo"
        },
        {
          "data": "titulo"
        },
        {
          "data": "colortexto"
        },
        {
          "data": "colorfondo"
        },
        {
          "data": "horainicio"
        },
        {
          "data": "horafin"
        },
        {
          "data": null,
          "orderable": false
        }
        ],
        columnDefs: [{
          targets: -1,
          className: 'dt-body-center',
          "defaultContent": "<button class='btn btn-sm btn-danger botonborrar'>Borra?</button>",
          data: null
        }, {
          targets: 1,
          className: 'dt-body-center'
        },
        {
          targets: 2,
          className: 'dt-body-center'
        }
        ],
        'rowCallback': function (row, data, index) {
          $(row).find('td:eq(1)').css('color', data.colortexto);
          $(row).find('td:eq(1)').css('background-color', data.colorfondo);
        },
        "language": {
          "url": "datatables/spanish.json",
        },
        "lengthMenu": [
          [10, 25, 50, -1],
          [10, 25, 50, "Todos"]
        ],
      });

Mediante la propiedad "ajax" se le indica que archivo debe llamar para recuperar en formato JSON los datos a mostrar:

        "ajax": {
          url: 'datoseventospredefinidos.php?accion=listar',
          dataSrc: ""
        },

En la propiedad "columns" indicamos cada uno de los campos a mostrar y si son columnas donde mostraremos botones inicializamos la propiedad "data" con el valor null:

        "columns": [{
          "data": "codigo"
        },
        {
          "data": "titulo"
        },
        {
          "data": "colortexto"
        },
        {
          "data": "colorfondo"
        },
        {
          "data": "horainicio"
        },
        {
          "data": "horafin"
        },
        {
          "data": null,
          "orderable": false
        }
        ],

Mediante la propiedad "columnDefs" especificamos la columna que mostrará el botón de borrar:

        columnDefs: [{
          targets: -1,
          className: 'dt-body-center',
          "defaultContent": "<button class='btn btn-sm btn-danger botonborrar'>Borra?</button>",
          data: null
        }, {

Mediante la propiedad 'rowCallback' hemos cambiado el color de texto y fondo de la segunda columna de la tabla:

        'rowCallback': function (row, data, index) {
          $(row).find('td:eq(1)').css('color', data.colortexto);
          $(row).find('td:eq(1)').css('background-color', data.colorfondo);
        },

Disponemos de una gran cantidad de propiedades que podemos configurar cuando creamos un objeto de la clase DataTables, siempre debemos tener a mano la documentación oficial del plug-in DataTables.

Carga de un evento predefinido

Cuando se presiona el botón 'Agregar evento predefinido' se ejecuta la función que tiene por objetivo hacer visible el diálogo que permite cargar un evento predefinido:

      $('#BotonAgregar').click(function () {
        limpiarFormulario();
        $("#FormularioEventosPredefinidos").modal();
      });

La interfaz visual del diálogo es:

Calendario de eventos php

Al presionar el botón de "Confirmar" se dispara la función:

      $('#BotonConfirmarAgregar').click(function () {
        let registro = recuperarDatosFormulario();
        agregarRegistro(registro);
        $("#FormularioEventosPredefinidos").modal('hide');
      });

La función recupera los datos cargados en el formulario y procede a llamar a la función 'agregarRegistro'. Además oculta el diálogo.

La función 'agregarRegistro' se comunica con el servidor para proceder a cargar el evento predefinido:

      function agregarRegistro(registro) {
        $.ajax({
          type: 'POST',
          url: 'datoseventospredefinidos.php?accion=agregar',
          data: registro,
          success: function (msg) {
            tabla1.ajax.reload();
          },
          error: function (error) {
            alert("Hay un problema:" + error);
          }
        });
      }

Como podemos controlar se llama la pagina 'datoseventospredefinidos.php?accion=agregar' y se le pasa la acción de 'agregar', luego el algoritmo que se ejecuta en el archivo 'datoseventospredefinidos.php' es:

<?php
header('Content-Type: application/json');

require("conexion.php");

$conexion = retornarConexion();

switch ($_GET['accion']) {
    case 'listar':
        $datos = mysqli_query($conexion, "select codigo,titulo,horainicio,horafin,colortexto,colorfondo from eventospredefinidos");
        $resultado = mysqli_fetch_all($datos, MYSQLI_ASSOC);
        echo json_encode($resultado);
        break;

    case 'agregar':
        $respuesta = mysqli_query($conexion, "insert into eventospredefinidos(titulo,horainicio,horafin,colortexto,colorfondo) values 
                                                ('$_POST[titulo]','$_POST[horainicio]','$_POST[horafin]','$_POST[colortexto]','$_POST[colorfondo]')");
        echo json_encode($respuesta);
        break;

    case 'borrar':
        $respuesta = mysqli_query($conexion, "delete from eventospredefinidos where codigo=$_POST[codigo]");
        echo json_encode($respuesta);
        break;
}
?>

Como vemos se efectúa un 'insert' en la tabla 'eventospredefinidos'.

Borrado de un evento predefinido

Habíamos visto que cada fila de la tabla tiene un botón, el cual podemos detectar cuando se ha presionado mediante la función:

      $('#tabla1 tbody').on('click', 'button.botonborrar', function () {
        if (confirm("Realmente quiere borrar el evento predefinido?")) {
          let registro = tabla1.row($(this).parents('tr')).data();
          borrarRegistro(registro);
        }
      });

Primero pedimos confirmar si realmente queremos borrar el evento predefinido, en caso afirmativo procedemos a rescatar todos los datos de la fila de la tabla y llamamos a la función 'borrarRegistro'.

La función 'borrarRegistro':

      function borrarRegistro(registro) {
        $.ajax({
          type: 'POST',
          url: 'datoseventospredefinidos.php?accion=borrar',
          data: registro,
          success: function (msg) {
            tabla1.ajax.reload();
          },
          error: function (error) {
            alert("Hay un problema:" + error);
          }
        });
      }

Procede a llamar a la página 'datoseventospredefinidos.php?accion=borrar' pasando como acción la cadena 'borrar'.

En el archivo 'datoseventospredefinidos.php' se elimina la fila respectiva:

    case 'borrar':
        $respuesta = mysqli_query($conexion, "delete from eventospredefinidos where codigo=$_POST[codigo]");
        echo json_encode($respuesta);
        break;