1/*1789636316000*/ 2/** 3 * Definición de los campos de los eventos 4 * 5 * @param data[] 6 * @param data[].fecha_inicio 7 * @param data[].fecha_fin 8 * @param data[].lugar 9 * @param data[].descripcion 10 * @param data[].horario 11 * @param data[].organismo 12 * @param data[].email_contacto 13 * @param data[].persona_contacto 14 * @param data[].telf_contacto 15 * @param data[].direccion_contacto 16 * @param data[].url_imagen 17 * @param data[].url_tv 18 * @param data[].url_pdf_boletin_oficial 19 * @param data[].referencia_publicacion 20 * @param data[].titulo 21 * @param data[].anexo_imagen_carrusel 22 * @param data[].etiqueta_categoria 23 * @param data[].fecha_plazo_inicio 24 * @param data[].fecha_plazo_fin 25 * @param data[].unidad 26 * @param data[].organismo 27 * @param data[].solicitudes 28 * @param data[].destinatarios 29 * @param data[].duracion 30 * @param data[].anexos 31 * @param data[].texto_realizacion 32 * @param data[].texto_plazo 33 * @param data[].resultados 34 * @param data[].url_agenda 35 * @param category[] 36 * @param category[].id_categoria 37 * @param category[].etiqueta_categoria 38 */ 39 40(function ($) { 41 const BASE_URL_ATTR = 'data-baseurl'; 42 const VIEW_PARAM = 'tipoconsulta'; 43 const DATE_URL_PARAM = 'fecha'; 44 const SEARCH_URL_PARAM = 'busqueda'; 45 const QUERY_URL_PARAM = 'q'; 46 const DAY_URL_PARAM = 'dia'; 47 const TODAY_URL_PARAM = 'hoy'; 48 const WEEK_URL_PARAM = 'proximasemana'; 49 const MONTH_URL_PARAM = 'proximomes'; 50 const SOON_URL_PARAM = 'proximamente'; 51 const PREV_URL_PARAM = 'anteriores'; 52 const CATEGORY_URL_PARAM = 'categoria'; 53 const PAGE_SEARCH_PARAM = '&page='; 54 const PAGE_LINK_SELECTOR = '.page-link'; 55 56 let baseUrl; 57 let getUrlParameter; 58 59 const monthNames = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']; 60 const listLinksMessages = []; 61 62 listLinksMessages[DAY_URL_PARAM] = 'el dÃa '; 63 listLinksMessages[WEEK_URL_PARAM] = 'durante la próxima semana'; 64 listLinksMessages[MONTH_URL_PARAM] = 'durante el próximo mes'; 65 listLinksMessages[SEARCH_URL_PARAM] = 'para la búsqueda '; 66 listLinksMessages[SOON_URL_PARAM] = 'próximamente'; 67 listLinksMessages[TODAY_URL_PARAM] = 'hoy'; 68 69 function _isNaN(o) { 70 // eslint-disable-next-line no-restricted-globals 71 return typeof o === 'number' && isNaN(o); 72 } 73 74 function _isValidServiceDate(value) { 75 let parts; 76 let d; 77 let m; 78 let y; 79 let date; 80 81 if (!value || value === '--') return false; 82 parts = String(value).split('-'); 83 if (parts.length !== 3) return false; 84 d = parseInt(parts[0], 10); 85 m = parseInt(parts[1], 10); 86 y = parseInt(parts[2], 10); 87 if (_isNaN(d) || _isNaN(m) || _isNaN(y)) return false; 88 date = new Date(y, m - 1, d); 89 return date.getFullYear() === y && date.getMonth() === m - 1 && date.getDate() === d; 90 } 91 92 function _clean(value) { 93 if (value === undefined || value === null) return ''; 94 const text = String(value).trim(); 95 return (text === '' || text === '--') ? '' : value; 96 } 97 98 /** 99 * Indica si la fecha introducida es correcta. 100 * 101 * Una fecha correcta se considera aquella que al menos está formada por año y mes, y además los 102 * datos introducidos forman una fecha válida. 103 * @param date in aaaa-dd-mm format 104 * @returns {boolean} 105 * @private 106 */ 107 function _isValidDate(date) { 108 let day; 109 let month; 110 let year; 111 let dateArray; 112 let monthNumber; 113 let auxDate; 114 115 if (date) { 116 dateArray = date.split('-'); 117 year = dateArray[0]; 118 month = dateArray[1]; 119 day = dateArray[2]; 120 121 if (typeof year !== 'undefined' && typeof month !== 'undefined') { 122 monthNumber = parseInt(month, 10) - 1; 123 124 if (monthNumber >= 0 && monthNumber <= 11) { 125 if (typeof day !== 'undefined') { 126 auxDate = new Date(parseInt(year, 10), parseInt(month, 10) - 1, parseInt(day, 10)); 127 } else { 128 auxDate = new Date(parseInt(year, 10), parseInt(month, 10) - 1); 129 } 130 131 return Object.prototype.toString.call(auxDate) === '[object Date]' && !_isNaN(auxDate.getTime()); 132 } 133 } 134 } 135 136 return false;
137 } 138 139 /** 140 * Comprueba si una categorÃa forma parte de aquellas para las que debe mostrarle la vista de 141 * eventos de plazo abierto por defecto. 142 */ 143 function _isSoonCategory(category) { 144 const soonCategories = ['261', '311']; 145 return soonCategories.indexOf(category) !== -1; 146 } 147 148 // Fuente: https://stackoverflow.com/questions/16941104/remove-a-parameter-to-the-url-with-javascript 149 function _removeURLParameter(key, sourceURL) { 150 let i; 151 let rtn = sourceURL.split('?')[0]; 152 let param; 153 let paramsArr = []; 154 const queryString = (sourceURL.indexOf('?') !== -1) ? sourceURL.split('?')[1] : ''; 155 if (queryString !== '') { 156 paramsArr = queryString.split('&'); 157 for (i = paramsArr.length - 1; i >= 0; i -= 1) { 158 param = paramsArr[i].split('=')[0]; 159 if (param === key) { 160 paramsArr.splice(i, 1); 161 } 162 } 163 if (paramsArr.length > 0) { 164 rtn = rtn + '?' + paramsArr.join('&'); 165 } 166 } 167 return rtn; 168 } 169 170 function _buildEventListUrl(date) { 171 return baseUrl + '?' + VIEW_PARAM + '=dia&fecha=' + date; 172 } 173 174 function _goToDate(date) { 175 let today; 176 let dateParam; 177 178 // Si faltan datos, se muestran los eventos del dÃa actual (si no hay mes o dÃa). 179 if (!_isValidDate(date)) { 180 today = new Date(); 181 dateParam = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate(); 182 } else { 183 dateParam = date; 184 } 185 186 window.location.href = _buildEventListUrl(dateParam); 187 } 188 189 function _getDateString(startDate, endDate) { 190 if (startDate !== '') { 191 if (endDate !== '') { 192 return (endDate === startDate ? startDate : 'Del ' + startDate + ' al ' + endDate); 193 } 194 195 return startDate; 196 } 197 198 return endDate || ''; 199 } 200 201 function _getCurrentDate() { 202 // La fecha en la URL viene en formato yyyy-mm-dd 203 const date = getUrlParameter(DATE_URL_PARAM); 204 let today; 205 let day; 206 let month; 207 let year; 208 209 if (!_isValidDate(date)) { 210 today = new Date(); 211 year = today.getFullYear(); 212 month = ('0' + (today.getMonth() + 1)).slice(-2); 213 day = today.getDate(); 214 return [year, month, day].join('-'); 215 } 216 return date; 217 } 218 219 /**
220 * Construye la URL de una petición para el servicio de agenda 221 * @param jsonBaseUrl La URL base del servicio 222 * @param view La vista (tipo de consulta) solicitada 223 * @param dateParam La fecha de la consulta, si tiene 224 * @param isCategoriesUrl Indica si es una URL para obtener las categorÃas de una consulta 225 * @param page La página a obtener en una consulta con paginación. Null si no hay paginación. 226 * @param scope El ámbito de la consulta, si tiene. 227 * @returns {string} La URL completa de la consulta a realizar al servicio. 228 * @private 229 */ 230 function _buildRequestUrl(jsonBaseUrl, view, dateParam, isCategoriesUrl, page, scope) { 231 let jsonUrl = jsonBaseUrl; 232 let q; 233 const category = getUrlParameter(CATEGORY_URL_PARAM); 234 const hasPagination = page !== null; 235 236 if (!view || view === DAY_URL_PARAM || view === TODAY_URL_PARAM) { 237 jsonUrl += '?tipoconsulta=dia&fecha_inicio=' + dateParam; 238 } else if (view === WEEK_URL_PARAM || view === MONTH_URL_PARAM || view === SOON_URL_PARAM) { 239 jsonUrl += '?tipoconsulta=' + view; 240 } else if (view === SEARCH_URL_PARAM) { 241 if (!isCategoriesUrl) { 242 jsonUrl = 'https://www.um.es/ws-siu/agenda/busqueda.php'; 243 } 244 q = getUrlParameter(QUERY_URL_PARAM); 245 if (q) { 246 jsonUrl += '?q=' + q; 247 248 if (hasPagination && !_isNaN(page)) { 249 jsonUrl += '&paginacion=si' + PAGE_SEARCH_PARAM + page; 250 } 251 } 252 } else if (view === PREV_URL_PARAM) { 253 jsonUrl += '?tipoconsulta=' + view; 254 255 if (hasPagination && !_isNaN(page)) { 256 jsonUrl += '&paginacion=si' + PAGE_SEARCH_PARAM + page; 257 } 258 } 259 260 // Comprueba el filtro de categorÃas 261 if (category) { 262 jsonUrl += '&categoria=' + category; 263 } 264 265 // Comprueba el ámbito de la búsqueda 266 if (scope) { 267 jsonUrl += '&ambito=' + scope; 268 } 269 270 return jsonUrl; 271 } 272 273 function _printDataColumns(label, content, type, linkText) { 274 let formattedText; 275 const aText = (typeof linkText !== 'undefined' ? linkText : content); 276 const columnLabel = (label !== '' ? '<b>' + label + '</b>:' : ''); 277 let dataColumn = '<div class="col-xs-12 as-detalle__info-item">'; 278 279 if (type !== 'nolabel') { 280 dataColumn += columnLabel + ' '; 281 } 282 283 if (type === 'link') { 284 formattedText = '<a href="' + content + '">' + aText + '</a>'; 285 } else if (type === 'email') { 286 formattedText = '<a href="mailto:' + content + '">' + aText + '</a>'; 287 } else { 288 formattedText = content; 289 } 290 291 dataColumn += ' <span class="visible-xs-inline"><br/></span>' + formattedText + '</div>'; 292 293 return dataColumn; 294 } 295 296 function _ddmmyyyyToDayStamp(dateString) { 297 let dateArray; 298 299 if (dateString) { 300 dateArray = dateString.split('-'); 301 return new Date(parseInt(dateArray[2], 10), 302 parseInt(dateArray[1], 10) - 1, 303 parseInt(dateArray[0], 10)).getTime(); 304 } 305 306 return new Date().setHours(0, 0, 0, 0); 307 } 308 309 function _yyyymmddToDayStamp(dateString) { 310 let dateArray; 311 312 if (dateString) { 313 dateArray = dateString.split('-'); 314 return new Date(parseInt(dateArray[0], 10), 315 parseInt(dateArray[1], 10) - 1, 316 parseInt(dateArray[2], 10)).getTime(); 317 } 318 319 return new Date().setHours(0, 0, 0, 0); 320 } 321 322 /** 323 * Comprueba si un rango de fecha se superpone a otro mayor 324 * @param aStart number fecha de inicio del rango menor 325 * @param aEnd number fecha de fin del rango menor 326 * @param bStart number fecha de inicio del rango mayor 327 * @param bEnd number fecha de fin del rango menor 328 * @returns {boolean} 329 */ 330 function _dateRangeOverlaps(aStart, aEnd, bStart, bEnd) { 331 if (aStart <= bStart && bStart <= aEnd) return true; // b starts in a 332 if (aStart <= bEnd && bEnd <= aEnd) return true; // b ends in a 333 if (bStart < aStart && aEnd < bEnd) return true; // a in b 334 return false; 335 } 336 337 function _buildPagination($p, currentPage, lastPage) { 338 const $firstPage = $('.primera'); 339 const $prevPage = $('.anterior'); 340 const $currentPage = $('.actual'); 341 const $nextPage = $('.siguiente'); 342 const $lastPage = $('.ultima'); 343 const isFirstPage = currentPage === 1; 344 const isLastPage = currentPage === lastPage; 345 const currentPageText = currentPage + ' de ' + lastPage; 346 347 // Resetea la navegación 348 $p.find('.page-item').removeClass('disabled'); 349 350 // Añade el número de la página actual 351 $currentPage.find(PAGE_LINK_SELECTOR).text(currentPageText); 352 353 /* Si es la primera página inhabilita los controles para ir a página anterior y primera. 354 * En caso contrario añade el valor al botón de página anterior. */ 355 if (isFirstPage) { 356 $firstPage.addClass('disabled').attr('data-page', -1); 357 $prevPage.addClass('disabled').attr('data-page', -1); 358 $firstPage.find(PAGE_LINK_SELECTOR).attr('data-page', -1); 359 $prevPage.find(PAGE_LINK_SELECTOR).attr('data-page', -1); 360 } else { 361 $firstPage.find(PAGE_LINK_SELECTOR).attr('data-page', 1); 362 $prevPage.find(PAGE_LINK_SELECTOR).attr('data-page', parseInt(currentPage, 10) - 1); 363 } 364 365 /* Si es la última página inhabilita los controles para ir a página siguiente y última. 366 * En caso contrario añade los valores de los botones de página siguiente y última. */ 367 if (isLastPage) { 368 $nextPage.addClass('disabled'); 369 $lastPage.addClass('disabled'); 370 $nextPage.find(PAGE_LINK_SELECTOR).attr('data-page', -1); 371 $lastPage.find(PAGE_LINK_SELECTOR).attr('data-page', -1); 372 } else { 373 $nextPage.find(PAGE_LINK_SELECTOR).attr('data-page', parseInt(currentPage, 10) + 1); 374 $lastPage.find(PAGE_LINK_SELECTOR).attr('data-page', lastPage); 375 } 376 } 377 378 function _initListado($listado) { 379 let dateParts; 380 let textoMensajes; 381 const dateParam = _getCurrentDate(); 382 const currentDay = _yyyymmddToDayStamp(dateParam); 383 const jsonBaseUrl = $listado.attr('data-jsonurl'); 384 const defaultView = $listado.attr('data-defaultview') || 'dia'; 385 let detailUrl = $listado.attr('data-detalleurl') || 'https://www.um.es/web/agenda'; 386 const view = getUrlParameter(VIEW_PARAM) || defaultView; 387 const category = getUrlParameter('categoria'); 388 const $pagination = $listado.find('.as-listado__paginacion'); 389 const $prevEventsPagination = $('.as-listado__anteriores-paginacion .pagination'); 390 const isSearch = view === SEARCH_URL_PARAM; 391 const hasPagination = isSearch; // De momento solo hay paginación en la búsqueda. 392 const scope = $listado.attr('data-scope'); 393 const isSingleView = $listado.attr('data-issingleview') === 'true'; 394 const pageParam = getUrlParameter('page') || '1'; 395 396 /* Se detecta la vista por defecto si: 397 * - defaultView y view son iguales 398 * - no hay parámetro fecha en la URL */ 399 const isDefaultView = defaultView === view && !getUrlParameter(DATE_URL_PARAM); 400 401 /* Solo se muestran actividades anteriores si se está viendo la vista por defecto, si están 402 activadas y si el ámbito es distinto de Agenda Universidad de Murcia (ámbito 1) */ 403 const displayPreviousActivities = isDefaultView && scope !== '1' && $('.lista-anteriores-container').length > 0; 404 405 // Forma la URL de la petición a partir de los parámetros recibidos 406 const jsonUrl = _buildRequestUrl(jsonBaseUrl, view, dateParam, false, pageParam, scope); 407 408 /* Función local únicamente para el listado. Cambia los eventos visibles (hoy/plazo abierto) */ 409 const _toggleVisibles = function () { 410 $listado.find('.as-listado__cabecera--hoy, .as-listado__cabecera--plazo, .actividad--activo, .actividad--en-plazo').toggleClass('d-none'); 411 }; 412 413 /* Función local para listado; construye la lista de actividades anteriores */ 414 const _buildPrevActivitiesList = function (page) { 415 const $list = $listado.find('.lista-anteriores'); 416 const jsonPrevUrl = _buildRequestUrl(jsonBaseUrl, PREV_URL_PARAM, null, false, page, scope); 417 418 $.get(jsonPrevUrl, (data) => { 419 const previousActivitiesCount = data['numero-total-items']; 420 const activitiesToDisplay = data.resultados || []; 421 const lastPage = data['numero-paginas']; 422 423 // Muestra la cuenta total de actividades 424 $('.total-registros-anteriores').text(previousActivitiesCount); 425 426 // Construye el listado 427 $list.empty(); 428 activitiesToDisplay.forEach((event) => { 429 let textoMostrar; 430 let dateString; 431 let eventDetailUrl = event.url_agenda; 432 const eventTitle = _clean(event.titulo); 433 const $template = $listado.find('.plantilla-actividad .actividad'); 434 const $eventNode = $template.clone(); 435 const $nodeDate = $eventNode.find('.actividad__fecha'); 436 const $nodeTerm = $eventNode.find('.actividad__plazo'); 437 const $nodeLocation = $eventNode.find('.actividad__lugar'); 438 439 // Imagen 440 if (_clean(event.anexo_imagen_carrusel)) { 441 $eventNode.find('.actividad__imagen img').attr('src', event.anexo_imagen_carrusel).attr('alt', eventTitle); 442 } 443 444 // CategorÃa 445 if (_clean(event.etiqueta_categoria)) { 446 $eventNode.find('.actividad__categoria').text(event.etiqueta_categoria); 447 } else { 448 $eventNode.find('.actividad__categoria').remove(); 449 } 450 451 /* Construye el enlace para eventos sin ámbito Universidad de Murcia */ 452 if (!eventDetailUrl || eventDetailUrl === '--') { 453 $eventNode.find('.actividad__titulo').text(eventTitle || ''); 454 } else { 455 if (!eventDetailUrl.startsWith('http')) { 456 if (!detailUrl.endsWith('/')) { 457 detailUrl += '/'; 458 } 459 eventDetailUrl = detailUrl + eventDetailUrl; 460 } 461 // TÃtulo y enlace 462 $eventNode.find('.actividad__titulo a').attr('href', eventDetailUrl).text(eventTitle); 463 } 464 465 /* Fecha de realización: Se muestra el campo texto_realizacion si existe. En caso 466 * contrario se muestra la fecha y el horario. Si no hay fecha_inicio se considera que el 467 * evento no tiene fecha de realización y no se muestra */ 468 if (_clean(event.texto_realizacion)) { 469 $nodeDate.html(event.texto_realizacion); 470 } else if (_isValidServiceDate(event.fecha_inicio)) { 471 dateString = _getDateString(event.fecha_inicio, _isValidServiceDate(event.fecha_fin) ? event.fecha_fin : ''); 472 473 if (_clean(event.horario)) { 474 dateString += ' - ' + event.horario; 475 } 476 477 $nodeDate.text(dateString); 478 } else { 479 $nodeDate.remove(); 480 } 481 482 /* Fecha de plazo: Se muestra el campo texto_plazo si existe. En caso contrario se muestra 483 * la fecha. Si no hay fecha_plazo_fin se considera que el evento no tiene fecha de plazo 484 * y no se muestra este dato */ 485 if (_clean(event.texto_plazo)) { 486 $nodeTerm.text(event.texto_plazo); 487 } else if (_isValidServiceDate(event.fecha_plazo_fin)) { 488 textoMostrar = ''; 489 490 if (_isValidServiceDate(event.fecha_plazo_inicio)) { 491 textoMostrar += 'Plazo: '; 492 } else { 493 textoMostrar += 'Fin de plazo: '; 494 } 495 496 textoMostrar += _getDateString( 497 _isValidServiceDate(event.fecha_plazo_inicio) ? event.fecha_plazo_inicio : '', 498 event.fecha_plazo_fin 499 ); 500 $nodeTerm.text(textoMostrar); 501 } else { 502 $nodeTerm.remove(); 503 } 504 505 if (_clean(event.lugar)) { 506 $nodeLocation.append(event.lugar); 507 } else { 508 $nodeLocation.remove(); 509 } 510 511 $list.append($eventNode); 512 }); 513 514 // Construye la paginación 515 _buildPagination($prevEventsPagination, page, lastPage); 516 }); 517 }; 518 519 // Completa los mensajes de la parte superior 520 textoMensajes = listLinksMessages[view]; 521 522 // En vista de dÃa, construye el mensaje que indica el dÃa del que se muestran los eventos 523 if (view === DAY_URL_PARAM) { 524 dateParts = dateParam.split('-'); 525 textoMensajes += dateParts[2] + ' de ' + monthNames[parseInt(dateParts[1], 10) - 1] + ' de ' + dateParts[0]; 526 } 527 528 $listado.find('.as-listado__texto--hoy, .as-listado__texto--plazo').text(textoMensajes); 529 530 // Realiza la petición de los datos del listado 531 $.get(jsonUrl) 532 .done((data) => { 533 let pagesText; 534 let $resultInfoText; 535 let searchUrl; 536 let activeEventsCount = 0; 537 let soonEventsCount = 0; 538 539 /* En caso de búsqueda, muestra la cabecera con la información de búsqueda y oculta la 540 * cabecera estándar. También comprueba si debe llevar o no paginación. 541 */ 542 if (isSearch) { 543 $resultInfoText = $listado.find('.as-listado__cabecera--info-resultados'); 544 $resultInfoText.find('.total-registros').text(data['total-registros']); 545 $resultInfoText.find('.consulta').text(data['consulta-realizada']); 546 $listado.find('.as-listado__cabecera--busqueda').removeClass('d-none'); 547 $listado.find('.as-listado__cabecera').remove(); 548 } else { 549 $listado.find('.as-listado__cabecera').removeClass('d-none'); 550 $listado.find('.as-listado__cabecera--busqueda').remove(); 551 $pagination.remove(); 552 } 553 554 if (isSingleView) { 555 $listado.find('.as-listado__cabecera--subtitulo-hoy').hide(); 556 } 557 558 // Comprueba si hay resultados y los recorre para dibujarlos 559 if (data.resultados && data.resultados.length > 0) { 560 data.resultados.forEach((event) => { 561 let dateString; 562 let textoMostrar; 563 let rangeStartDay; 564 let rangeEndDay; 565 let daysToAdd; 566 let eventDetailUrl = event.url_agenda; 567 const $template = $listado.find('.plantilla-actividad .actividad'); 568 const $list = $listado.find('.lista-actividades'); 569 const $eventNode = $template.clone(); 570 const eventTitle = _clean(event.titulo); 571 const $nodeDate = $eventNode.find('.actividad__fecha'); 572 const $nodeTerm = $eventNode.find('.actividad__plazo'); 573 const $nodeLocation = $eventNode.find('.actividad__lugar'); 574 575 let startDay; 576 let endDay; 577 /* En vista única todos los eventos son activos, si no inicializa a fal
577so */ 578 let isActiveEvent = isSingleView; 579 580 /* Comprueba si es un evento activo o está en plazo si no es vista única */ 581 // Si el listado es de un dÃa concreto (hoy o por fecha) 582 if (!isSingleView) { 583 if (view === DAY_URL_PARAM) { 584 if (_isValidServiceDate(event.fecha_inicio)) { 585 startDay = _ddmmyyyyToDayStamp(event.fecha_inicio); 586 587 if (_isValidServiceDate(event.fecha_fin)) { 588 endDay = _ddmmyyyyToDayStamp(event.fecha_fin); 589 isActiveEvent = startDay <= currentDay && currentDay <= endDay; 590 } else { 591 isActiveEvent = startDay === currentDay; 592 } 593 } 594 } else if (view === WEEK_URL_PARAM || view === MONTH_URL_PARAM) { 595 /* Si el listado muestra la vista semana o mes, compara los rangos de fechas 596 * para saber si es un evento activo o en plazo. 597 * - Si no hay fecha inicio asume que es un evento en plazo. 598 * - Si no hay fecha de fin asume que es un evento de un solo dÃa. 599 */ 600 if (_isValidServiceDate(event.fecha_inicio)) { 601 daysToAdd = (view === WEEK_URL_PARAM ? 7 : 30); 602 rangeStartDay = currentDay; 603 rangeEndDay = new Date(dateParam.valueOf()); 604 rangeEndDay.setDate(rangeEndDay.getDate() + daysToAdd); 605 rangeEndDay = rangeEndDay.setHours(0, 0, 0, 0); 606 startDay = _ddmmyyyyToDayStamp(event.fecha_inicio); 607 608 if (_isValidServiceDate(event.fecha_fin)) { 609 endDay = _ddmmyyyyToDayStamp(event.fecha_fin); 610 } else { 611 endDay = startDay; 612 } 613 614 isActiveEvent = _dateRangeOverlaps(startDay, endDay, rangeStartDay, rangeEndDay); 615 } 616 } else if (view === SOON_URL_PARAM) { 617 isActiveEvent = _isValidServiceDate(event.fecha_inicio); 618 } else if (view === SEARCH_URL_PARAM) { 619 /* Fuerza que todos los eventos se muestren en la misma sección en caso de búsqueda 620 * para no diferenciar entre eventos activos y en plazo */ 621 isActiveEvent = true; 622 } 623 } 624 625 /* Categoriza el nodo según las fechas e incrementa la cuenta de eventos de hoy o en 626 plazo si no es búsqueda */ 627 if (isActiveEvent) { 628 activeEventsCount += 1; 629 $eventNode.addClass('actividad--activo'); 630 } else { 631 soonEventsCount += 1; 632 // Los eventos en plazo se ocultan por defecto con la clase .d-none 633 $eventNode.addClass('actividad--en-plazo d-none'); 634 } 635 636 // Imagen 637 if (_clean(event.anexo_imagen_carrusel)) { 638 $eventNode.find('.actividad__imagen img').attr('src', event.anexo_imagen_carrusel).attr('alt', eventTitle); 639 } 640 641 // CategorÃa 642 if (_clean(event.etiqueta_categoria)) { 643 $eventNode.find('.actividad__categoria').text(event.etiqueta_categoria); 644 } else { 645 $eventNode.find('.actividad__categoria').remove(); 646 } 647 648 /* Construye el enlace para eventos sin ámbito Universidad de Murcia */ 649 if (!eventDetailUrl || eventDetailUrl === '--') { 650 $eventNode.find('.actividad__titulo').text(eventTitle || ''); 651 } else { 652 if (!eventDetailUrl.startsWith('http')) { 653 if (!detailUrl.endsWith('/')) { 654 detailUrl += '/'; 655 } 656 eventDetailUrl = detailUrl + eventDetailUrl; 657 } 658 // TÃtulo y enlace 659 $eventNode.find('.actividad__titulo a').attr('href', eventDetailUrl).text(eventTitle); 660 } 661 662 /* Fecha de realización: Se muestra el campo texto_realizacion si existe. En caso 663 * contrario se muestra la fecha y el horario. Si no hay fecha_inicio se considera que 664 * el evento no tiene fecha de realización y no se muestra */ 665 if (_clean(event.texto_realizacion)) { 666 $nodeDate.html(event.texto_realizacion); 667 } else if (_isValidServiceDate(event.fecha_inicio)) { 668 dateString = _getDateString(event.fecha_inicio, _isValidServiceDate(event.fecha_fin) ? event.fecha_fin : ''); 669 670 if (_clean(event.horario)) { 671 dateString += ' - ' + event.horario; 672 } 673 674 $nodeDate.text(dateString); 675 } else { 676 $nodeDate.remove(); 677 } 678 679 /* Fecha de plazo: Se muestra el campo texto_plazo si existe. En caso contrario se 680 * muestra la fecha. Si no hay fecha_plazo_fin se considera que el evento no tiene fecha 681 * de plazo y no se muestra este dato */ 682 if (_clean(event.texto_plazo)) { 683 $nodeTerm.text(event.texto_plazo); 684 } else if (_isValidServiceDate(event.fecha_plazo_fin)) { 685 textoMostrar = ''; 686 687 if (_isValidServiceDate(event.fecha_plazo_inicio)) { 688 textoMostrar += 'Plazo: '; 689 } else { 690 textoMostrar += 'Fin de plazo: '; 691 } 692 693 textoMostrar += _getDateString( 694 _isValidServiceDate(event.fecha_plazo_inicio) ? event.fecha_plazo_inicio : '', 695 event.fecha_plazo_fin 696 ); 697 $nodeTerm.text(textoMostrar); 698 } else { 699 $nodeTerm.remove(); 700 } 701 702 if (_clean(event.lugar)) { 703 $nodeLocation.append(event.lugar); 704 } else { 705 $nodeLocation.remove(); 706 } 707 708 $list.append($eventNode); 709 }); 710 711 // Si es búsqueda, construye la paginación y habilita los textos adecuados 712 if (isSearch) { 713 // Limpia de la URL el término de la búsqueda 714 searchUrl = _removeURLParameter('page', window.location.href) + PAGE_SEARCH_PARAM; 715 716 if (hasPagination) { 717 $pagination.removeClass('d-none'); 718 // Mensaje de página actual 719 pagesText = 'Página ' + data['pagina-actual'] + ' de ' + data['numero-paginas']; 720 721 // Asigna valores a los campos de páginas primera y anterior de la paginación 722 if (data['pagina-anterior'] !== '') { 723 $pagination.find('.primera').attr('href', searchUrl + '1'); 724 $pagination.find('.anterior').attr('href', searchUrl + data['pagina-anterior']); 725 } else { 726 $pagination.find('.primera').parent('li').remove(); 727 $pagination.find('.anterior').parent('li').remove(); 728 } 729 730 // Asigna valores a los campos de páginas siguiente y última de la paginación 731 if (data['pagina-siguiente'] !== '') { 732 $pagination.find('.siguiente').attr('href', searchUrl + data['pagina-siguiente']); 733 $pagination.find('.ultima').attr('href', searchUrl + data['numero-paginas']); 734 } else { 735 $pagination.find('.siguiente').parent('li').remove(); 736 $pagination.find('.ultima').parent('li').remove(); 737 } 738 $pagination.find('.actual').text(pagesText); 739 } 740 } else { 741 // Si no es búsqueda completa los campos de información de número de eventos 742 $listado.find('.as-listado__numero--hoy').text('(' + activeEventsCount + ')'); 743 744 $pagination.remove(); 745 746 if (!isSingleView) { 747 $listado.find('.as-listado__numero--plazo').text('(' + soonEventsCount + ')'); 748 } 749 } 750 } else if (!isSearch) { 751 $listado.find('.sin-resultados').removeClass('d-none'); 752 } 753 754 /* Cambia la vista por defecto a Plazo abierto para determinadas categorÃas */ 755 if (!isSingleView && _isSoonCategory(category)) { 756 _toggleVisibles(); 757 } 758 759 // Añade eventos de click 760 if (!isSingleView) {
761 $listado.on('click', '.as-listado__cambia-vista', (event) => { 762 _toggleVisibles(); 763 event.preventDefault(); 764 }); 765 } 766 }) 767 .always(() => { 768 $listado.find('.lista-actividades .loading-animation').addClass('d-none'); 769 }); 770 771 // Listado de anteriores 772 if (displayPreviousActivities) { 773 $('.lista-anteriores-container').removeClass('d-none'); 774 _buildPrevActivitiesList(1); 775 776 // Evento para la navegación por las páginas 777 $prevEventsPagination.on('click', PAGE_LINK_SELECTOR, (event) => { 778 const targetPage = $(event.currentTarget).attr('data-page'); 779 event.preventDefault(); 780 if (targetPage !== '-1') { 781 _buildPrevActivitiesList(parseInt(targetPage, 10)); 782 } 783 }); 784 } 785 } 786 787 function _initCalendario($calendar) { 788 let menuLinksString = ''; 789 const menuLinks = { 790 hoy: 'Hoy', 791 proximasemana: 'Próxima Semana', 792 proximomes: 'Próximo mes' 793 }; 794 795 const options = { 796 autosize: true, 797 onSelect: _goToDate, 798 'dateFormat': 'yy-mm-dd' 799 }; 800 801 $.datepicker.setDefaults( 802 $.extend( 803 { 'dateFormat': 'yy-mm-dd' }, $.datepicker.regional.es 804 ) 805 ); 806 807 baseUrl = $calendar.attr(BASE_URL_ATTR); 808 $calendar.removeAttr(BASE_URL_ATTR); 809 $calendar.datepicker(options); 810 811 /* Crea un enlace por cada elemento de menuLinks */ 812 Object.keys(menuLinks).forEach((key) => { 813 let menuLinkHref; 814 if (Object.hasOwnProperty.call(menuLinks, key)) { 815 menuLinkHref = baseUrl; 816 if (key !== TODAY_URL_PARAM) { 817 menuLinkHref += '?' + VIEW_PARAM + '=' + key; 818 } 819 menuLinksString += '<a class="as-calendario__date-filter" href="' + menuLinkHref + '">' + menuLinks[key] + '</a>'; 820 } 821 }); 822 823 $calendar.prepend(menuLinksString); 824 825 $(document).on('click', '.ui-datepicker-next, .ui-datepicker-prev', (event) => { 826 event.stopPropagation(); 827 }); 828 } 829 830 function _initMenu($menu) { 831 let paramCharacter; 832 let jsonBaseUrl; 833 let currentLocation; 834 const view = getUrlParameter(VIEW_PARAM); 835 const currentDate = _getCurrentDate(); 836 const scope = $menu.attr('data-scope'); 837 const categoriesUrl = _buildRequestUrl($menu.attr('data-jsoncategorias'), view, currentDate, true, null, scope); 838 839 if (categoriesUrl) { 840 /* Si la página actual es listado, añade categorÃa a la selección actual. 841 Si no, enlaza el listado con la categorÃa */ 842 jsonBaseUrl = ($('.as-listado__nuevo').length ? window.location.href : $menu.attr('data-baseUrl')); 843 // Obtiene la URL para el enlace quitando la categorÃa anterior,no debe ser acumulativo 844 currentLocation = _removeURLParameter('categoria', jsonBaseUrl); 845 paramCharacter = (currentLocation.indexOf('?') > -1 ? '&' : '?'); 846 847 // Obtiene la lista de categorÃas y construye el selector 848 $.get(categoriesUrl, (data) => { 849 const $categoryList = $menu.find('.menu__enlace--categoria').next(); 850 851 if (Array.isArray(data) && data.length > 0) { 852 data.forEach((category) => { 853 if (!_clean(category.id_categoria)) return; 854 const categoryUrl = currentLocation + paramCharacter + 'categoria=' + category.id_categoria; 855 $categoryList.append('<li><a href="' + categoryUrl + '">' + _clean(category.etiqueta_categoria) + '</a></li>'); 856 }); 857 } else { 858 $categoryList.append('<li>No hay categorÃas disponibles</li>'); 859 } 860 }); 861 } 862 } 863 864 function _initVistaDetalle($detail) { 865 let jsonUrl; 866 const id = getUrlParameter('id'); 867 const $loadingSpinner = $('.detalle-loading-animation'); 868 869 if (!id) { 870 window.location.href = $detail.attr('data-listadourl'); 871 } else { 872 jsonUrl = $detail.attr('data-jsonurl') + '?id=' + id; 873 874 if (jsonUrl !== '') { 875 // Obtiene los datos por Ajax 876 $.get(jsonUrl) 877 .done((data) => { 878 let evento; 879 let $error; 880 let firstFile; 881 let $publicacion; 882 let $contacto; 883 let hayMasInfo; 884 let hayPublicacion; 885 let hayContacto; 886 let fechaMostrar; 887 const $organizacion = $detail.find('.as-detalle__organizacion'); 888 let plazoMostrar = ''; 889 890 if (data && data.length > 0) { 891 evento = data[0]; 892 893 // TÃtulo 894 $detail.find('.as-detalle__titulo').text(_clean(evento.titulo)); 895 $detail.find('.as-detalle__categoria').text(_clean(evento.etiqueta_categoria)); 896 897 // Imagen 898 if (evento.anexo_imagen_carrusel) { 899 $detail.find('.as-detalle__imagen').attr('src', evento.anexo_imagen_carrusel); 900 } else { 901 $detail.find('.as-detalle__imagen').parent().remove(); 902 } 903 904 // Fecha de realización 905 if (_clean(evento.texto_realizacion)) { 906 fechaMostrar = evento.texto_realizacion; 907 } else if (_isValidServiceDate(evento.fecha_inicio)) { 908 fechaMostrar = _getDateString(evento.fecha_inicio, _isValidServiceDate(evento.fecha_fin) ? evento.fecha_fin : ''); 909 } 910 911 if (fechaMostrar) { 912 $detail.find('.as-detalle__fechas').append(fechaMostrar); 913 } else { 914 $detail.find('.as-detalle__fechas').remove(); 915 } 916 917 // Hora 918 if (_clean(evento.horario)) { 919 $detail.find('.as-detalle__horas').append(evento.horario); 920 } else { 921 $detail.find('.as-detalle__horas').remove(); 922 } 923 924 // Lugar 925 if (_clean(evento.lugar)) { 926 $detail.find('.as-detalle__lugar').append(evento.lugar); 927 } else { 928 $detail.find('.as-detalle__lugar').remove(); 929 } 930 931 // Fecha plazo 932 if (_clean(evento.texto_plazo)) { 933 if (_clean(evento.solicitudes)) { 934 plazoMostrar += evento.solicitudes + '<ul><li>'; 935 } 936 937 plazoMostrar += evento.texto_plazo; 938 939 if (_clean(evento.solicitudes)) { 940 plazoMostrar += '</li></ul>'; 941 } 942 } else { 943 if (_clean(evento.solicitudes)) { 944 plazoMostrar += '<b>Solicitudes</b>: ' + evento.solicitudes; 945 } 946 947 if (_isValidServiceDate(evento.fecha_plazo_fin)) { 948 if (_clean(evento.solicitudes)) { 949 plazoMostrar += '<ul><li>'; 950 } 951 952 if (!_isValidServiceDate(evento.fecha_plazo_inicio)) { 953 plazoMostrar += '<b>Fin de plazo</b>: ' + evento.fecha_plazo_fin; 954 } else { 955 plazoMostrar += 'Plazo: ' + _getDateString(evento.fecha_plazo_inicio, evento.fecha_plazo_fin); 956 } 957 958 if (_clean(evento.solicitudes)) { 959 plazoMostrar += '</li></ul>'; 960 } 961 } 962 } 963 964 if (plazoMostrar) { 965 $detail.find('.as-detalle__plazo').append(plazoMostrar); 966 } else { 967 $detail.find('.as-detalle__plazo').remove(); 968 } 969 970 // Retransmisión en directo 971 if (_clean(evento.url_tv)) { 972 $detail.find('.as-detalle__directo a').attr('href', evento.url_tv); 973 } else { 974 $detail.find('.as-detalle__directo').remove(); 975 } 976 977 // Organismo y Unidad (Organización) 978 if (_clean(evento.organismo)) { 979 $organizacion.append(_printDataColumns('Organismo', evento.organismo)); 980 } 981 982 if (_clean(evento.unidad)) { 983 $organizacion.append(_printDataColumns('Unidad', evento.unidad)); 984 } 985 986 // Destinatarios 987 if (_clean(evento.destinatarios)) { 988 $organizacion.append(_printDataColumns('Destinatarios', evento.destinatarios)); 989 } 990 991 // Duración 992 if (_clean(evento.duracion)) { 993 $organizacion.append(_printDataColumns('Duración', evento.duracion)); 994 } 995 996 if ($organizacion.is(':empty')) { 997 $organizacion.remove(); 998 } 999 1000 // Descripción 1001 if (_clean(evento.descripcion)) { 1002 $detail.find('.as-detalle__descripcion').html(evento.descripcion); 1003 } else { 1004 $detail.find('.as-detalle__descripcion, .descripcion__titulo').remove(); 1005 } 1006 1007 // Más información (Datos de contacto, publicación) 1008 hayContacto = _clean(evento.persona_contacto) || _clean(evento.email_contacto) 1009 || _clean(evento.telf_contacto) || _clean(evento.direccion_contacto); 1010 hayPublicacion = evento.url || _clean(evento.anexos); 1011 hayMasInfo = hayContacto || hayPublicacion; 1012 1013 if (hayMasInfo) { 1014 $contacto = $detail.find('#info-seccion-contacto'); 1015 $publicacion = $detail.find('#info-seccion-publicacion'); 1016 1017 // Datos de contacto 1018 if (hayContacto) { 1019 if (_clean(evento.persona_contacto)) { 1020 $contacto.append(_printDataColumns('Persona', evento.persona_contacto, 'nolabel')); 1021 } 1022 1023 if (_clean(evento.email_contacto)) { 1024 $contacto.append(_printDataColumns('Correo', evento.email_contacto, 'email')); 1025 } 1026 1027 if (_clean(evento.telf_contacto)) { 1028 $contacto.append(_printDataColumns('Teléfono', evento.telf_contacto)); 1029 } 1030 1031 if (_clean(evento.direccion_contacto)) { 1032 $contacto.append(_printDataColumns('Dirección', evento.direccion_contacto)); 1033 } 1034 } else { 1035 $detail.find('.mas-info__item--contacto').remove(); 1036 $contacto.remove(); 1037 } 1038 1039 // Datos de publicación 1040 if (hayPublicacion) { 1041 if (evento.url) { 1042 $publicacion.append(_printDataColumns('Web', evento.url, 'link', 'Enlace página web')); 1043 } 1044 1045 if (_clean(evento.anexos)) { 1046 firstFile = true; 1047 evento.anexos.split('#').forEach((anexo) => { 1048 const anexoArray = anexo.split('|'); 1049 if (anexoArray.length < 2 || !_clean(anexoArray[0])) return; 1050 let label; 1051 if (firstFile) { 1052 label = 'Documentos'; 1053 firstFile = false;
1054 } else { 1055 label = ''; 1056 } 1057 1058 $publicacion.append(_printDataColumns(label, anexoArray[0], 'link', anexoArray[1])); 1059 }); 1060 } 1061 } else { 1062 $detail.find('#info-seccion-publicacion').remove(); 1063 $publicacion.remove(); 1064 } 1065 } else { 1066 $detail.find('.mas-info__titulo, .mas-info, .as-detalle__info-seccion').remove(); 1067 } 1068 1069 // Mostramos el contenido una vez se ha terminado de completar 1070 $detail.removeClass('d-none'); 1071 } else { 1072 $error = $detail.next(); 1073 if ($error.length > 0) { 1074 $error.removeClass('d-none'); 1075 } 1076 } 1077 }) 1078 .always(() => { 1079 $loadingSpinner.addClass('d-none'); 1080 }); 1081 } 1082 } 1083 } 1084 1085 // eslint-disable-next-line no-param-reassign 1086 $.fn.agendaSiu = function () { 1087 getUrlParameter = UM.Utils.getUrlParameter; 1088 return this.each(function () { 1089 const $this = $(this); 1090 if ($this.hasClass('as-calendario__nuevo')) { 1091 _initCalendario($this); 1092 } else if ($this.hasClass('as-listado__nuevo')) { 1093 _initListado($this); 1094 } else if ($this.hasClass('as-detalle__nuevo')) { 1095 _initVistaDetalle($this); 1096 } else if ($this.hasClass('as-menu__nuevo')) { 1097 _initMenu($this); 1098 } 1099 }); 1100 }; 1101}(jQuery)); 1102 1103/* Polyfills */ 1104 1105if (!String.prototype.startsWith) { 1106 // eslint-disable-next-line no-extend-native 1107 String.prototype.startsWith = function (stringBuscada, posicion = 0) { 1108 return this.indexOf(stringBuscada, posicion) === posicion; 1109 }; 1110} 1111 1112if (!String.prototype.endsWith) { 1113 // eslint-disable-next-line no-extend-native 1114 String.prototype.endsWith = function (searchString, positionParam) { 1115 let position = positionParam; 1116 const subjectString = this.toString(); 1117 // eslint-disable-next-line no-restricted-globals 1118 if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { 1119 position = subjectString.length; 1120 } 1121 position -= searchString.length; 1122 const lastIndex = subjectString.indexOf(searchString, position); 1123 return lastIndex !== -1 && lastIndex === position; 1124 }; 1125}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.