{"id":1840,"date":"2026-03-17T12:01:12","date_gmt":"2026-03-17T18:01:12","guid":{"rendered":"https:\/\/www.cusur.udg.mx\/web\/?page_id=1840"},"modified":"2026-03-19T13:20:54","modified_gmt":"2026-03-19T19:20:54","slug":"horarios-cusur","status":"publish","type":"page","link":"https:\/\/www.cusur.udg.mx\/web\/horarios-cusur\/","title":{"rendered":"Horarios CUSur"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"1840\" class=\"elementor elementor-1840\" data-elementor-post-type=\"page\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-7bad44a elementor-section-full_width elementor-hidden-mobile elementor-section-height-default elementor-section-height-default\" data-id=\"7bad44a\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;background_background&quot;:&quot;gradient&quot;}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-no\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-0d90460\" data-id=\"0d90460\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-90f6d2e elementor-widget elementor-widget-image\" data-id=\"90f6d2e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"800\" height=\"212\" src=\"https:\/\/www.cusur.udg.mx\/web\/adjuntos\/2026\/03\/banner_horarios-1024x271.png\" class=\"attachment-large size-large wp-image-1854\" alt=\"\" srcset=\"https:\/\/www.cusur.udg.mx\/web\/adjuntos\/2026\/03\/banner_horarios-1024x271.png 1024w, https:\/\/www.cusur.udg.mx\/web\/adjuntos\/2026\/03\/banner_horarios-300x79.png 300w, https:\/\/www.cusur.udg.mx\/web\/adjuntos\/2026\/03\/banner_horarios-768x203.png 768w, https:\/\/www.cusur.udg.mx\/web\/adjuntos\/2026\/03\/banner_horarios-1536x406.png 1536w, https:\/\/www.cusur.udg.mx\/web\/adjuntos\/2026\/03\/banner_horarios-2048x541.png 2048w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-e998f93 elementor-section-full_width elementor-hidden-desktop elementor-hidden-tablet elementor-section-height-default elementor-section-height-default\" data-id=\"e998f93\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-no\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-6437805\" data-id=\"6437805\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-dc3514f elementor-widget elementor-widget-image\" data-id=\"dc3514f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"800\" height=\"628\" src=\"https:\/\/www.cusur.udg.mx\/web\/adjuntos\/2026\/03\/banner-horarios-small-1024x804.png\" class=\"attachment-large size-large wp-image-1855\" alt=\"\" srcset=\"https:\/\/www.cusur.udg.mx\/web\/adjuntos\/2026\/03\/banner-horarios-small-1024x804.png 1024w, https:\/\/www.cusur.udg.mx\/web\/adjuntos\/2026\/03\/banner-horarios-small-300x235.png 300w, https:\/\/www.cusur.udg.mx\/web\/adjuntos\/2026\/03\/banner-horarios-small-768x603.png 768w, https:\/\/www.cusur.udg.mx\/web\/adjuntos\/2026\/03\/banner-horarios-small-1536x1205.png 1536w, https:\/\/www.cusur.udg.mx\/web\/adjuntos\/2026\/03\/banner-horarios-small-2048x1607.png 2048w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-1727d78 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"1727d78\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-4a06756\" data-id=\"4a06756\" data-element_type=\"column\" data-e-type=\"column\" data-settings=\"{&quot;background_background&quot;:&quot;gradient&quot;}\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-016fb1b elementor-widget elementor-widget-shortcode\" data-id=\"016fb1b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><!-- \r\n  M\u00d3DULO: Consulta y ordenamiento de horarios\r\n\r\n  DESCRIPCI\u00d3N GENERAL:\r\n  Este bloque renderiza la interfaz de consulta de horarios dentro de WordPress.\r\n  Incluye:\r\n  1. Filtros por ciclo escolar, programa acad\u00e9mico y departamento.\r\n  2. Campo de b\u00fasqueda.\r\n  3. Tabla de resultados con opci\u00f3n de ordenamiento por encabezado.\r\n\r\n  AJUSTE REALIZADO:\r\n  Se sobrescribi\u00f3 la funci\u00f3n global sortTable() para optimizar el ordenamiento\r\n  de columnas, ya que la implementaci\u00f3n original provocaba lentitud o bloqueo\r\n  de la p\u00e1gina al ordenar varias veces o trabajar con muchas filas.\r\n\r\n  BENEFICIO:\r\n  La nueva l\u00f3gica ordena las filas en memoria y luego actualiza el tbody\r\n  de una sola vez, reduciendo la manipulaci\u00f3n directa del DOM y mejorando\r\n  la fluidez de la p\u00e1gina.\r\n-->\r\n\r\n<div>&nbsp;<\/div>\r\n\r\n<p>&nbsp;<\/p>\r\n\r\n<!-- Fuentes y estilos externos -->\r\n<link href=\"https:\/\/fonts.googleapis.com\/css?family=Open+Sans\" rel=\"stylesheet\" \/>\r\n<link href=\"https:\/\/fonts.googleapis.com\/css?family=Raleway\" rel=\"stylesheet\" \/>\r\n<link href=\"https:\/\/cusur.udg.mx\/horarios\/public\/css\/styles.css\" rel=\"stylesheet\" \/>\r\n\r\n<style>\r\n\r\n\/* =========================================\r\n   ESTILOS GENERALES DEL M\u00d3DULO\r\n ========================================= *\/\r\n\r\n\/* CONTENEDOR PRINCIPAL M\u00c1S AMPLIO *\/\r\n.container-fluid-custom {\r\n    padding: 24px 0 20px;\r\n    max-width: 100%;\r\n    width: 100%;\r\n    font-family: 'Open Sans', sans-serif;\r\n}\r\n.filters-card::before {\r\n    content: \"\";\r\n    position: absolute;\r\n    top: 0;\r\n    left: 0;\r\n    width: 100%;\r\n    height: 4px;\r\n    background: linear-gradient(90deg, #e1ecf7, #eee3bb);\r\n}\r\n\t\r\n\/* TARJETA VISUAL PARA LA ZONA DE FILTROS *\/\r\n.filters-card {\r\n    background: rgba(255,255,255,0.72);\r\n    backdrop-filter: blur(8px);\r\n    -webkit-backdrop-filter: blur(8px);\r\n   border: 1px solid rgba(255,255,255,0.7);\r\n    border-radius: 22px;\r\n    padding: 24px 28px;\r\n    box-shadow: 0 12px 30px rgba(0,0,0,0.05);\r\n    margin: 0 auto 34px;\r\n\tposition: relative;\r\n    overflow: hidden;\r\n}\r\n\r\n\/* Etiquetas de los filtros con mejor jerarqu\u00eda visual *\/\r\n.filters-card label,\r\n.form-group label {\r\n    display: block;\r\n    font-size: 14px;\r\n    font-weight: 700;\r\n    color: #2f4f7f;\r\n    margin-bottom: 8px;\r\n    letter-spacing: 0.2px;\r\n}\r\n\r\n\/* FILTROS: Ciclo y Programa en la misma l\u00ednea *\/\r\n.filters-grid {\r\n    display: flex;\r\n    gap: 26px;\r\n    flex-wrap: wrap;\r\n    margin-bottom: 18px;\r\n}\r\n\r\n\/* Tama\u00f1os proporcionales de los bloques de filtro *\/\r\n.filter-item-small { \r\n    flex: 1; \r\n    min-width: 200px; \r\n}\r\n\r\n.filter-item-large { \r\n    flex: 2; \r\n    min-width: 300px; \r\n}\r\n\r\n\/* Separaci\u00f3n sutil antes del bloque de b\u00fasqueda *\/\r\n#DepartamentoFormGroup {\r\n    margin-bottom: 8px;\r\n}\r\n\r\n\/* =========================================\r\n   CAMPOS DE FORMULARIO Y B\u00daSQUEDA\r\n   ========================================= *\/\r\n\/* INPUTS Y SELECTS CON HOVER *\/\r\n.form-control, .my-formControl {\r\n    border: 1px solid #d7e0ea !important;\r\n    border-radius: 16px !important;\r\n    height: 52px !important;\r\n    font-size: 15px !important;\r\n    padding: 0 16px !important;\r\n    background: rgba(255,255,255,0.92) !important;\r\n    transition: all 0.25s ease !important;\r\n    box-shadow: none !important;\r\n}\r\n\r\n\/* Efecto visual al pasar el cursor *\/\r\n.form-control:hover, .my-formControl:hover {\r\n    border-color: #9cbbe3 !important;\r\n    box-shadow: 0 6px 16px rgba(0,0,0,0.05) !important;\r\n    background-color: #ffffff !important;\r\n}\r\n\r\n\/* Estado de enfoque para mejorar accesibilidad y est\u00e9tica *\/\r\n.form-control:focus, .my-formControl:focus {\r\n    border-color: #3f6fb0 !important;\r\n    box-shadow: 0 0 0 4px rgba(63,111,176,0.12) !important;\r\n    outline: none !important;\r\n}\r\n\r\n\/* Contenedor del buscador y bot\u00f3n *\/\r\n.search-block {\r\n    margin: 22px 0 0;\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 10px;\r\n    flex-wrap: wrap;\r\n}\r\n\r\n\/* Campo de b\u00fasqueda flexible *\/\r\n.search-block .my-formControl {\r\n    flex: 0 1 360px;\r\n    min-width: 240px;\r\n    max-width: 360px;\r\n}\r\n\r\n\/* Bot\u00f3n de b\u00fasqueda *\/\r\n#buttonSearch {\r\n    background: linear-gradient(135deg, #7FA8D8, #5b8cd8) !important;\r\n    color: white !important;\r\n    border-radius: 14px !important;\r\n    padding: 0 22px !important;\r\n    height: 50px !important;\r\n    min-width: 72px;\r\n    font-size: 16px;\r\n    font-weight: 700;\r\n    border: none !important;\r\n    cursor: pointer;\r\n    transition: all 0.25s ease;\r\n    box-shadow: 0 10px 22px rgba(44,82,130,0.22);\r\n}\r\n\t\r\n\/* Efecto hover del bot\u00f3n *\/\r\n#buttonSearch:hover { \r\n    background: linear-gradient(135deg, #2f5fa3, #5a84c1) !important;\r\n    transform: translateY(-1px);\r\n    box-shadow: 0 12px 26px rgba(44,82,130,0.28);\r\n}\r\n\r\n\/* INSTRUCCI\u00d3N *\/\r\n.table-instruction {\r\n    color: #3b69b0;\r\n    margin-bottom: 14px;\r\n    font-size: 15px;\r\n\tfont-weight: 700;\r\n    padding-left: 2px;\r\n\tdisplay: flex;\r\n    align-items: center;\r\n    gap: 8px;\r\n}\r\n\t\r\n\/* =========================================\r\n   TABLA DE RESULTADOS\r\n ========================================= *\/\r\n\/* Contenedor visual de la tabla *\/\r\n.table-responsive {\r\n    border-radius: 18px;\r\n    box-shadow: 0 12px 30px rgba(31,56,88,0.08);\r\n    overflow: hidden;\r\n    width: calc(100vw - 110px);\r\n    max-width: calc(100vw - 110px);\r\n    margin-left: calc(50% - 50vw + 60px);\r\n    background: #ffffff;\r\n    border: 1px solid #e7edf5;\r\n}\r\n\r\n\/* Configuraci\u00f3n general de la tabla *\/\r\n#myTable {\r\n    width: 100%;\r\n    table-layout: fixed;\r\n    background: white;\r\n    border-collapse: separate;\r\n    border-spacing: 0;\r\n}\r\n\r\n\/* ENCABEZADOS *\/\r\n#myTable thead th {\r\nbackground: #5b8cd8;\r\ncolor: white;\r\nfont-size: 13px;\r\nfont-weight: 700;\r\npadding: 13px 8px;\r\nborder-right: 1px solid rgba(255,255,255,0.07);\r\n\tletter-spacing: 0.3px;\r\n\t\r\n    text-transform: uppercase;\r\n    text-align: center;\r\n    cursor: pointer;\r\n    line-height: 1.25;\r\n    word-break: break-word;\r\n    overflow-wrap: break-word;\r\n}\r\n\t\r\n\t#myTable thead th:first-child {\r\n    border-top-left-radius: 16px;\r\n}\r\n\r\n#myTable thead th:last-child {\r\n    border-top-right-radius: 16px;\r\n}\r\n\r\n\t#myTable thead th {\r\n    transition: background 0.25s ease, color 0.25s ease;\r\n}\r\n\r\n#myTable thead th:hover {\r\n    background: #5a84c1;\r\n    color: #ffffff;\r\n}\r\n\t\r\n\r\n\r\n\/* CELDAS *\/\r\n#myTable tbody td {\r\n    padding: 14px 8px;\r\n    font-size: 14px;\r\n    text-align: center;\r\n    border-bottom: 1px solid #E6EEF7;\r\n    border-right: 1px solid #E6EEF7;\r\n    vertical-align: top;\r\n    color: #404142;\r\n    line-height: 1.45;\r\n    word-break: break-word;\r\n    overflow-wrap: break-word;\r\n    white-space: normal;\r\n}\r\n\r\n\/* Columnas largas alineadas a la izquierda *\/\r\n#myTable tbody td:nth-child(1),\r\n#myTable tbody td:nth-child(4),\r\n#myTable tbody td:nth-child(5),\r\n#myTable tbody td:nth-child(8) {\r\n    text-align: left;\r\n}\r\n\r\n\/* Anchos espec\u00edficos por columna *\/\r\n#myTable th:nth-child(1),  #myTable td:nth-child(1)  { width: 9%; }   \/* Programa *\/\r\n#myTable th:nth-child(2),  #myTable td:nth-child(2)  { width: 6%; }   \/* Grupo *\/\r\n#myTable th:nth-child(3),  #myTable td:nth-child(3)  { width: 7%; }   \/* Clave *\/\r\n#myTable th:nth-child(4),  #myTable td:nth-child(4)  { width: 13%; }  \/* Materia *\/\r\n#myTable th:nth-child(5),  #myTable td:nth-child(5)  { width: 14%; }  \/* Departamento *\/\r\n#myTable th:nth-child(6),  #myTable td:nth-child(6)  { width: 7%; }   \/* Secci\u00f3n *\/\r\n#myTable th:nth-child(7),  #myTable td:nth-child(7)  { width: 7%; }   \/* CRN *\/\r\n#myTable th:nth-child(8),  #myTable td:nth-child(8)  { width: 11%; }  \/* Profesor *\/\r\n#myTable th:nth-child(9),  #myTable td:nth-child(9)  { width: 8%; }   \/* D\u00eda *\/\r\n#myTable th:nth-child(10), #myTable td:nth-child(10) { width: 8%; }   \/* Hora *\/\r\n#myTable th:nth-child(11), #myTable td:nth-child(11) { width: 9%; }   \/* Fechas *\/\r\n#myTable th:nth-child(12), #myTable td:nth-child(12) { width: 6%; }   \/* Aula *\/\r\n\r\n\/* Bordes finales *\/\r\n#myTable tbody td:last-child,\r\n#myTable thead th:last-child {\r\n    border-right: none;\r\n}\r\n\r\n#myTable tbody tr:last-child td {\r\n    border-bottom: none;\r\n}\r\n\r\n\/* Celdas impares *\/\r\n#myTable tbody td {\r\n    background-color: #FBFCFE;\r\n}\r\n\r\n\/* Celdas pares *\/\r\n#myTable tbody tr:nth-child(even) td {\r\n    background-color: #EAF2FB;\r\n}\r\n\r\n\r\n#myTable tbody tr:hover td {\r\n    background-color:  #DCEAF8;\r\n    transition: background-color 0.2s ease;\r\n}\r\n\r\n\/* =========================================\r\n   AJUSTES RESPONSIVE\r\n========================================= *\/\r\n\t\r\n\/* Ajustes generales para pantallas menores a 991px *\/\r\n@media (max-width: 991px) {\r\n    .container-fluid-custom {\r\n        max-width: 100%;\r\n        padding: 18px 8px;\r\n    }\r\n\r\n    \/* La tarjeta se compacta en pantallas medianas *\/\r\n    .filters-card {\r\n        padding: 24px 20px;\r\n        border-radius: 20px;\r\n        margin-bottom: 26px;\r\n    }\r\n\r\n    .filters-grid {\r\n        flex-direction: column;\r\n        gap: 14px;\r\n    }\r\n\r\n    .search-block {\r\n        flex-direction: column;\r\n        align-items: stretch;\r\n        gap: 12px;\r\n    }\r\n\r\n    .search-block .my-formControl {\r\n        max-width: 100%;\r\n        flex: 1 1 auto;\r\n    }\r\n\r\n    #buttonSearch {\r\n        width: 100%;\r\n    }\r\n}\r\n\t\r\n\/* =========================\r\n   RESPONSIVE - TABLET\r\n   ========================= *\/\r\n\r\n\/* Ajustes espec\u00edficos para tablet *\/\r\n@media (max-width: 991px) {\r\n    .container-fluid-custom {\r\n        width: 96%;\r\n        max-width: 96%;\r\n        margin: 0 auto;\r\n        padding: 16px 0;\r\n    }\r\n\r\n    .filters-grid {\r\n        display: flex;\r\n        gap: 16px;\r\n        flex-wrap: nowrap;\r\n        margin-bottom: 16px;\r\n    }\r\n\r\n    .filter-item-small {\r\n        flex: 1 1 32%;\r\n        min-width: 0;\r\n    }\r\n\r\n    .filter-item-large {\r\n        flex: 1 1 68%;\r\n        min-width: 0;\r\n    }\r\n\r\n    \/* Departamento a todo el ancho *\/\r\n    #DepartamentoFormGroup {\r\n        width: 100%;\r\n    }\r\n\r\n    \/* Buscador y bot\u00f3n en la misma fila *\/\r\n    .search-block {\r\n        display: flex;\r\n        flex-direction: row;\r\n        align-items: center;\r\n        gap: 12px;\r\n        margin: 24px 0 0;\r\n        flex-wrap: nowrap;\r\n    }\r\n\r\n    .search-block .my-formControl {\r\n        flex: 1 1 auto;\r\n        max-width: none;\r\n        min-width: 0;\r\n    }\r\n\r\n    #buttonSearch {\r\n        width: auto;\r\n        min-width: 96px;\r\n        height: 50px !important;\r\n        padding: 0 22px !important;\r\n        font-size: 16px;\r\n        flex: 0 0 auto;\r\n    }\r\n\r\n    .form-control,\r\n    .my-formControl {\r\n        height: 50px !important;\r\n        font-size: 15px !important;\r\n        border-radius: 14px !important;\r\n    }\r\n\r\n    .table-instruction {\r\n        font-size: 13px;\r\n        margin-bottom: 10px;\r\n        padding-left: 0;\r\n    }\r\n\r\n    \/* Tabla un poco m\u00e1s ancha en tablet *\/\r\n    .table-responsive {\r\n        width: 102%;\r\n        max-width: 102%;\r\n        margin-left: -1%;\r\n        overflow-x: auto;\r\n        -webkit-overflow-scrolling: touch;\r\n        border-radius: 12px;\r\n    }\r\n\r\n    #myTable {\r\n        min-width: 980px;\r\n    }\r\n\r\n    #myTable thead th {\r\n        font-size: 12px;\r\n        padding: 11px 7px;\r\n    }\r\n\r\n    #myTable tbody td {\r\n        font-size: 12px;\r\n        padding: 10px 7px;\r\n    }\r\n}\r\n\r\n\/* =========================\r\n   RESPONSIVE - M\u00d3VIL\r\n   ========================= *\/\r\n@media (max-width: 767px) {\r\n    .container-fluid-custom {\r\n        padding: 14px 6px;\r\n    }\r\n\r\n    .filters-card {\r\n        padding: 20px 16px;\r\n        border-radius: 18px;\r\n    }\r\n\r\n    .filters-grid {\r\n        gap: 10px;\r\n        margin-bottom: 12px;\r\n    }\r\n\r\n    .form-control,\r\n    .my-formControl {\r\n        height: 48px !important;\r\n        font-size: 14px !important;\r\n        border-radius: 14px !important;\r\n        padding: 0 14px !important;\r\n    }\r\n\r\n    .search-block {\r\n    margin: 18px 0 0;\r\n    gap: 10px;\r\n    display: flex;\r\n    flex-direction: row;\r\n    align-items: center;\r\n    flex-wrap: nowrap;\r\n}\r\n\t\r\n.search-block .my-formControl {\r\n    flex: 1 1 auto;\r\n    min-width: 0;\r\n    max-width: none;\r\n}\r\n\r\n    #buttonSearch {\r\n       height: 48px !important;\r\n      font-size: 15px;\r\n      padding: 0 18px !important;\r\n      min-width: 72px;\r\n      width: auto;\r\n    }\r\n\r\n    .table-instruction {\r\n        font-size: 13px;\r\n        line-height: 1.4;\r\n    }\r\n\r\n    .table-responsive {\r\n        border-radius: 10px;\r\n        width: 100%;\r\n        max-width: 100%;\r\n        margin-left: 0;\r\n        overflow-x: auto;\r\n        -webkit-overflow-scrolling: touch;\r\n    }\r\n\r\n    #myTable {\r\n        min-width: 980px; \/* para que no colapse la tabla *\/\r\n    }\r\n\r\n    #myTable thead th {\r\n        font-size: 12px;\r\n        padding: 10px 6px;\r\n        line-height: 1.2;\r\n    }\r\n\r\n    #myTable tbody td {\r\n        font-size: 12px;\r\n        padding: 9px 6px;\r\n        line-height: 1.3;\r\n    }\r\n}\r\n\r\n\/* =========================\r\n   RESPONSIVE - M\u00d3VIL PEQUE\u00d1O\r\n   ========================= *\/\r\n@media (max-width: 480px) {\r\n    .container-fluid-custom {\r\n        padding: 12px 4px;\r\n    }\r\n\r\n    .filters-card {\r\n        padding: 18px 14px;\r\n    }\r\n\r\n    .form-control,\r\n    .my-formControl {\r\n        font-size: 13px !important;\r\n        height: 46px !important;\r\n    }\r\n\r\n   .search-block {\r\n    display: flex;\r\n    flex-direction: row;\r\n    align-items: center;\r\n    flex-wrap: nowrap;\r\n}\r\n\r\n.search-block .my-formControl {\r\n    flex: 1 1 auto;\r\n    min-width: 0;\r\n    max-width: none;\r\n}\r\n\r\n#buttonSearch {\r\n    width: auto;\r\n    min-width: 68px;\r\n}\r\n\r\n    .table-instruction {\r\n        font-size: 12px;\r\n    }\r\n\r\n    #myTable {\r\n        min-width: 920px;\r\n    }\r\n\r\n    #myTable thead th {\r\n        font-size: 11px;\r\n        padding: 8px 5px;\r\n    }\r\n\r\n    #myTable tbody td {\r\n        font-size: 11px;\r\n        padding: 8px 5px;\r\n    }\r\n}\r\n\r\n\/* Ocultar columna C\u00f3digo (encabezado y celdas) *\/\r\n#myTable thead th:nth-child(8),\r\n#myTable tbody td:nth-child(8) {\r\n    display: none;\r\n\t}\r\n\r\n<\/style>\r\n\r\n<div class=\"container\">\r\n  <div class=\"row\">\r\n    <div class=\"container-fluid-custom\">\r\n\t\t<div class=\"filters-card\">\r\n\t\t\r\n      <!-- Filtro: ciclo escolar -->\r\n      <div class=\"filters-grid\">\r\n        <div class=\"filter-item-small\">\r\n          <div class=\"form-group\">\r\n            <label for=\"CicloEscolar\">Ciclo:<\/label>\r\n            <select class=\"form-control\" id=\"CicloEscolar\"><\/select>\r\n          <\/div>\r\n        <\/div>\r\n\r\n<!-- Filtro: programa acad\u00e9mico -->\r\n        <div class=\"filter-item-large\">\r\n          <div class=\"form-group\" id=\"ProgramaAcademicoFormGroup\">\r\n            <label for=\"ProgramaAcademico\">Programa:<\/label>\r\n            <select class=\"form-control\" id=\"ProgramaAcademico\"><\/select>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n<!-- Filtro: departamento -->\r\n      <div class=\"row\">\r\n        <div class=\"col-xs-12\">\r\n          <div class=\"form-group\" id=\"DepartamentoFormGroup\">\r\n            <label for=\"Departamento\">Departamento:<\/label>\r\n            <select class=\"form-control\" id=\"Departamento\"><\/select>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n<!-- \u00c1rea de b\u00fasqueda -->\r\n      <div class=\"search-block\">\r\n        <input class=\"my-formControl\" id=\"myInputSearch\" placeholder=\"Escribe para buscar...\" type=\"text\" style=\"flex: 1; max-width: 400px;\" \/>\r\n        <button id=\"buttonSearch\" type=\"button\">Ir<\/button>\r\n      <\/div>\r\n\t\t\t<\/div>\r\n\t\t\r\n      <span class=\"table-instruction\">\r\n        <i class=\"fa fa-info-circle\"><\/i> Haz clic en los encabezados para ordenar la informaci\u00f3n\r\n      <\/span>\r\n\r\n<!-- Tabla de resultados -->\r\n      <div class=\"table-responsive\">\r\n        <table class=\"table\" id=\"myTable\">\r\n          <thead>\r\n            <tr>\r\n              <th onclick=\"sortTable(0)\">Programa<\/th>\r\n              <th onclick=\"sortTable(1)\">Grupo<\/th>\r\n              <th onclick=\"sortTable(2)\">Clave<\/th>\r\n              <th onclick=\"sortTable(3)\">Materia<\/th>\r\n              <th onclick=\"sortTable(4)\">Departamento<\/th>\r\n              <th onclick=\"sortTable(5)\">Secci\u00f3n<\/th>\r\n              <th onclick=\"sortTable(6)\">CRN<\/th>\r\n              <th onclick=\"sortTable(7)\">C\u00f3digo<\/th>\r\n              <th onclick=\"sortTable(8)\">Profesor<\/th>\r\n              <th onclick=\"sortTable(9)\">D\u00eda<\/th>\r\n              <th onclick=\"sortTable(10)\">Hora<\/th>\r\n              <th onclick=\"sortTable(11)\">Fechas<\/th>\r\n              <th onclick=\"sortTable(12)\">Aula<\/th>\r\n            <\/tr>\r\n          <\/thead>\r\n<!-- \r\n            El nuevo ordenamiento trabaja \u00fanicamente sobre el tbody.\r\n            Esto evita afectar los encabezados y mejora el rendimiento.\r\n-->\r\n          <tbody id=\"HorariosTabla\">\r\n          <\/tbody>\r\n        <\/table>\r\n      <\/div>\r\n\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<!-- Librer\u00edas externas -->\r\n<!-- jQuery -->\r\n<script src=\"https:\/\/ajax.googleapis.com\/ajax\/libs\/jquery\/3.2.1\/jquery.min.js\"><\/script>\r\n\r\n<!-- Bootstrap JS -->\r\n<script src=\"https:\/\/maxcdn.bootstrapcdn.com\/bootstrap\/3.3.7\/js\/bootstrap.min.js\" integrity=\"sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa\" crossorigin=\"anonymous\"><\/script>\r\n\r\n<!-- Script original del sistema -->\r\n<!-- Scripts JS -->\r\n<script src=\"https:\/\/cusur.udg.mx\/horarios\/public\/js\/scripts.js\"><\/script>\r\n\r\n<script>\r\n\/* =========================================\r\n   CORRECCI\u00d3N DE TEXTO MAL CODIFICADO\r\n   ========================================= *\/\r\n\r\n\/*\r\n  Corrige caracteres da\u00f1ados por problemas de codificaci\u00f3n.\r\n  Ejemplo: \"\u00c3\u00a1\" se convierte en \"\u00e1\".\r\n*\/\r\nfunction fixBrokenText(text) {\r\n  if (!text) return \"\";\r\n\r\n  const map = {\r\n   '\u00c3\u00a1': '\u00e1', '\u00c3\u00a9': '\u00e9', '\u00c3\u00ad': '\u00ed', '\u00c3\u00b3': '\u00f3', '\u00c3\u00ba': '\u00fa',\r\n    '\u00c3\u0081': '\u00c1', '\u00c3\u2030': '\u00c9', '\u00c3\u008d': '\u00cd', '\u00c3\u201c': '\u00d3', '\u00c3\u0161': '\u00da',\r\n    '\u00c3\u2018': '\u00d1', '\u00c3\u0091': '\u00d1',\r\n    '\u00c3\u00b1': '\u00f1',\r\n    'N\u0303': '\u00d1', 'n\u0303': '\u00f1',\r\n    '\u00c3\u00bc': '\u00fc', '\u00c3\u0153': '\u00dc'\r\n  };\r\n\r\n  Object.keys(map).forEach(function(key) {\r\n    text = text.split(key).join(map[key]);\r\n  });\r\n\r\n  return text;\r\n}\r\n\r\n\/*\r\n  Aplica la correcci\u00f3n de texto a un nodo del DOM.\r\n*\/\r\nfunction fixNodeText(node) {\r\n  if (!node || !node.textContent) return;\r\n  node.textContent = fixBrokenText(node.textContent);\r\n}\r\n\r\n\/*\r\n  Corrige el texto de las opciones en los filtros:\r\n  - Departamento\r\n  - Programa acad\u00e9mico\r\n*\/\r\nfunction fixSelectText() {\r\n  document.querySelectorAll(\"#Departamento option, #ProgramaAcademico option\").forEach(function(option) {\r\n    fixNodeText(option);\r\n  });\r\n}\r\n\r\n\/*\r\n  Corrige solo las columnas de texto de la tabla.\r\n  Se procesan por bloques para evitar que la p\u00e1gina se trabe\r\n  cuando hay muchos resultados.\r\n*\/\r\nfunction fixTableText() {\r\n  const cells = Array.from(\r\n    document.querySelectorAll(\r\n      \"#HorariosTabla td:nth-child(1), \" +   \/* Programa *\/\r\n      \"#HorariosTabla td:nth-child(4), \" +   \/* Materia *\/\r\n      \"#HorariosTabla td:nth-child(5), \" +   \/* Departamento *\/\r\n      \"#HorariosTabla td:nth-child(9), \" +   \/* Profesor *\/\r\n      \"#HorariosTabla td:nth-child(10), \" +  \/* D\u00eda *\/\r\n      \"#HorariosTabla td:nth-child(12)\"      \/* Fechas *\/\r\n    )\r\n  );\r\n\r\n  let index = 0;\r\n  const chunkSize = 80;\r\n\r\n  function processChunk() {\r\n    const end = Math.min(index + chunkSize, cells.length);\r\n\r\n    for (let i = index; i < end; i++) {\r\n      fixNodeText(cells[i]);\r\n    }\r\n\r\n    index = end;\r\n\r\n    if (index < cells.length) {\r\n      setTimeout(processChunk, 0);\r\n    }\r\n  }\r\n\r\n  processChunk();\r\n}\r\n\r\n\/*\r\n  Al cargar la p\u00e1gina:\r\n  1. Corrige los selects con peque\u00f1os retrasos.\r\n  2. Observa el tbody para detectar nuevas filas.\r\n  3. Corrige la tabla cuando entren resultados nuevos.\r\n*\/\r\ndocument.addEventListener(\"DOMContentLoaded\", function () {\r\n  \/* Revisi\u00f3n escalonada de los selects *\/\r\n  setTimeout(fixSelectText, 300);\r\n  setTimeout(fixSelectText, 1000);\r\n  setTimeout(fixSelectText, 2000);\r\n\r\n  const tbody = document.getElementById(\"HorariosTabla\");\r\n  if (!tbody) return;\r\n\r\n  let debounceTimer = null;\r\n\r\n  \/*\r\n    Observa inserciones directas de filas en el tbody.\r\n    Cuando llegan nuevos resultados, lanza la correcci\u00f3n una sola vez.\r\n  *\/\r\n  const observer = new MutationObserver(function(mutations) {\r\n    let hasNewRows = false;\r\n\r\n    mutations.forEach(function(mutation) {\r\n      if (mutation.addedNodes && mutation.addedNodes.length > 0) {\r\n        hasNewRows = true;\r\n      }\r\n    });\r\n\r\n    if (!hasNewRows) return;\r\n\r\n    clearTimeout(debounceTimer);\r\n\r\n    debounceTimer = setTimeout(function() {\r\n      fixTableText();\r\n    }, 80);\r\n  });\r\n\r\n  observer.observe(tbody, { childList: true });\r\n\r\n  \/* Respaldo inicial por si ya existen datos al cargar *\/\r\n  setTimeout(fixTableText, 500);\r\n  setTimeout(fixTableText, 1500);\r\n});\r\n<\/script>\r\n\r\n<!-- \r\n  OPTIMIZACI\u00d3N LOCAL DE ORDENAMIENTO\r\n\r\n  Se sobrescribe la funci\u00f3n global sortTable() sin modificar el archivo externo.\r\n  La nueva versi\u00f3n:\r\n  - trabaja solo sobre las filas del tbody\r\n  - copia las filas a memoria\r\n  - las ordena con Array.sort()\r\n  - reconstruye la tabla en bloque con DocumentFragment\r\n-->\r\n<script>\r\n\/\/ Estado de orden por columna (asc \/ desc)\r\nwindow.sortState = {};\r\n\r\n\/\/ Obtiene el valor de una celda\r\nwindow.getCellValue = function(row, index) {\r\n  const cell = row.cells[index];\r\n  return cell ? cell.textContent.trim() : \"\";\r\n};\r\n\r\n\/\/ Convierte valores para comparaci\u00f3n (num\u00e9rico o texto)\r\nwindow.parseValue = function(value, columnIndex) {\r\n  const numericColumns = [1, 2, 5, 6, 7];\r\n\r\n  if (numericColumns.includes(columnIndex)) {\r\n    const num = parseFloat(value.replace(\/[^\\d.-]\/g, \"\"));\r\n    return isNaN(num) ? 0 : num;\r\n  }\r\n\r\n  return value.toLowerCase();\r\n};\r\n  \r\n\/\/ Nueva funci\u00f3n de ordenamiento optimizada\r\nwindow.sortTable = function(columnIndex) {\r\n  const tbody = document.getElementById(\"HorariosTabla\");\r\n\r\n  \/\/ Si no existe el tbody, se detiene la ejecuci\u00f3n evitando errores.\r\n  if (!tbody) return;\r\n\r\n  \/\/ Ordena solo las filas del tbody para evitar afectar encabezados\r\n  const rows = Array.from(tbody.querySelectorAll(\"tr\"));\r\n\r\n  \/\/ Si no hay filas, no hay nada que ordenar\r\n  if (!rows.length) return;\r\n\r\n  \/\/ Alterna asc\/desc, si ya estaba en asc, cambia a desc y viceversa\r\n  window.sortState[columnIndex] =\r\n    window.sortState[columnIndex] === \"asc\" ? \"desc\" : \"asc\";\r\n\r\n  const direction = window.sortState[columnIndex];\r\n\r\n  \/\/ Ordenamiento en memoria\r\n  \/\/ Se comparan los valores transformados por parseValue(), para que num y txt se ordenen.\r\n  rows.sort((a, b) => {\r\n    const aVal = window.parseValue(window.getCellValue(a, columnIndex), columnIndex);\r\n    const bVal = window.parseValue(window.getCellValue(b, columnIndex), columnIndex);\r\n\r\n    if (aVal < bVal) return direction === \"asc\" ? -1 : 1;\r\n    if (aVal > bVal) return direction === \"asc\" ? 1 : -1;\r\n    return 0;\r\n  });\r\n\r\n  \/\/ Reconstrucci\u00f3n eficiente de la tabla\r\n  const fragment = document.createDocumentFragment(); \/\/ Se reconstruye la tabla en bloque usando DocumentFragment\r\n  rows.forEach(row => fragment.appendChild(row));\r\n  \r\n  \/\/ Se limpia el contenido actual del tbody y se insertan las filas ya ordenadas\r\n  tbody.innerHTML = \"\";\r\n  tbody.appendChild(fragment);\r\n\t\r\n\t\/* Corrige el texto despu\u00e9s de ordenar *\/\r\nif (typeof fixTableText === \"function\") {\r\n  requestAnimationFrame(function() {\r\n    fixTableText();\r\n  });\r\n}\r\n};\r\n<\/script><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"","protected":false},"author":4,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1840","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.cusur.udg.mx\/web\/wp-json\/wp\/v2\/pages\/1840","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cusur.udg.mx\/web\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.cusur.udg.mx\/web\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.cusur.udg.mx\/web\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cusur.udg.mx\/web\/wp-json\/wp\/v2\/comments?post=1840"}],"version-history":[{"count":16,"href":"https:\/\/www.cusur.udg.mx\/web\/wp-json\/wp\/v2\/pages\/1840\/revisions"}],"predecessor-version":[{"id":1877,"href":"https:\/\/www.cusur.udg.mx\/web\/wp-json\/wp\/v2\/pages\/1840\/revisions\/1877"}],"wp:attachment":[{"href":"https:\/\/www.cusur.udg.mx\/web\/wp-json\/wp\/v2\/media?parent=1840"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}