543 lines
13 KiB
JavaScript
543 lines
13 KiB
JavaScript
(function (ventana, documento) {
|
|
"use strict";
|
|
|
|
var menuAbierto = null;
|
|
var botonMenuAbierto = null;
|
|
var origenMenuAbierto = null;
|
|
var eventosMenuRegistrados = false;
|
|
|
|
function inicializarCortinas(raiz) {
|
|
var cortinas = raiz.querySelectorAll(
|
|
"[data-sig-documentos-cortina]:not([data-sig-documentos-inicializada])"
|
|
);
|
|
|
|
Array.prototype.forEach.call(cortinas, function (cortina) {
|
|
var clave =
|
|
"documentos-etapa:" +
|
|
ventana.location.pathname +
|
|
":" +
|
|
cortina.id +
|
|
":" +
|
|
cortina.getAttribute("data-sig-documentos-cortina");
|
|
|
|
try {
|
|
var guardado = ventana.sessionStorage.getItem(clave);
|
|
|
|
if (
|
|
guardado !== null &&
|
|
cortina.getAttribute("data-sig-documentos-fija") !== "1"
|
|
) {
|
|
cortina.open = guardado === "1";
|
|
}
|
|
} catch (error) {
|
|
// Las cortinas siguen funcionando si el navegador limita el almacenamiento.
|
|
}
|
|
|
|
cortina.addEventListener("toggle", function () {
|
|
try {
|
|
ventana.sessionStorage.setItem(
|
|
clave,
|
|
cortina.open ? "1" : "0"
|
|
);
|
|
} catch (error) {
|
|
// No se requiere almacenamiento para abrir o cerrar la cortina.
|
|
}
|
|
});
|
|
|
|
cortina.setAttribute(
|
|
"data-sig-documentos-inicializada",
|
|
"1"
|
|
);
|
|
});
|
|
}
|
|
|
|
function cerrarMenuAcciones() {
|
|
if (!menuAbierto) {
|
|
return;
|
|
}
|
|
|
|
if (botonMenuAbierto) {
|
|
botonMenuAbierto.setAttribute(
|
|
"aria-expanded",
|
|
"false"
|
|
);
|
|
}
|
|
|
|
menuAbierto.classList.remove(
|
|
"sig-menu-acciones-flotante"
|
|
);
|
|
|
|
menuAbierto.removeAttribute("style");
|
|
|
|
if (
|
|
origenMenuAbierto &&
|
|
origenMenuAbierto.parentNode
|
|
) {
|
|
origenMenuAbierto.appendChild(menuAbierto);
|
|
} else if (menuAbierto.parentNode) {
|
|
menuAbierto.parentNode.removeChild(menuAbierto);
|
|
}
|
|
|
|
menuAbierto = null;
|
|
botonMenuAbierto = null;
|
|
origenMenuAbierto = null;
|
|
}
|
|
|
|
function obtenerFormulario() {
|
|
return documento.querySelector("form");
|
|
}
|
|
|
|
function posicionarMenu(menu, boton) {
|
|
var margen = 6;
|
|
var separacion = 4;
|
|
|
|
var rectangulo = boton.getBoundingClientRect();
|
|
|
|
var anchoVentana =
|
|
ventana.innerWidth ||
|
|
documento.documentElement.clientWidth;
|
|
|
|
var altoVentana =
|
|
ventana.innerHeight ||
|
|
documento.documentElement.clientHeight;
|
|
|
|
/*
|
|
* IMPORTANTE:
|
|
*
|
|
* Bootstrap puede dejar:
|
|
*
|
|
* right: 0;
|
|
*
|
|
* en dropdown-menu-right.
|
|
*
|
|
* Como este menú se mueve temporalmente al FORM,
|
|
* si dejamos left y right al mismo tiempo el menú
|
|
* puede estirarse prácticamente a todo el ancho.
|
|
*/
|
|
menu.style.position = "fixed";
|
|
menu.style.display = "block";
|
|
menu.style.visibility = "hidden";
|
|
|
|
menu.style.left = "0px";
|
|
menu.style.right = "auto";
|
|
menu.style.top = "0px";
|
|
menu.style.bottom = "auto";
|
|
|
|
/*
|
|
* El menú debe mantener un ancho compacto.
|
|
*/
|
|
menu.style.width = "auto";
|
|
menu.style.minWidth = "190px";
|
|
menu.style.maxWidth = "260px";
|
|
|
|
menu.style.boxSizing = "border-box";
|
|
|
|
/*
|
|
* Si la ventana es pequeña, permitimos scroll
|
|
* dentro del propio menú.
|
|
*/
|
|
menu.style.maxHeight =
|
|
Math.max(
|
|
80,
|
|
altoVentana - (margen * 2)
|
|
) + "px";
|
|
|
|
menu.style.overflowY = "auto";
|
|
menu.style.overflowX = "hidden";
|
|
|
|
/*
|
|
* Después de establecer el ancho correcto
|
|
* podemos medirlo.
|
|
*/
|
|
var anchoMenu = menu.offsetWidth;
|
|
var altoMenu = menu.offsetHeight;
|
|
|
|
var espacioAbajo =
|
|
altoVentana -
|
|
rectangulo.bottom -
|
|
margen;
|
|
|
|
var espacioArriba =
|
|
rectangulo.top -
|
|
margen;
|
|
|
|
var arriba;
|
|
|
|
/*
|
|
* Primero intentamos abrir hacia abajo.
|
|
*/
|
|
if (altoMenu <= espacioAbajo) {
|
|
arriba =
|
|
rectangulo.bottom +
|
|
separacion;
|
|
}
|
|
|
|
/*
|
|
* Si no cabe abajo pero sí arriba,
|
|
* abrimos arriba.
|
|
*/
|
|
else if (altoMenu <= espacioArriba) {
|
|
arriba =
|
|
rectangulo.top -
|
|
altoMenu -
|
|
separacion;
|
|
}
|
|
|
|
/*
|
|
* Si no cabe completo en ningún lado,
|
|
* utilizamos el lado con más espacio.
|
|
*/
|
|
else if (espacioAbajo >= espacioArriba) {
|
|
arriba =
|
|
rectangulo.bottom +
|
|
separacion;
|
|
|
|
menu.style.maxHeight =
|
|
Math.max(
|
|
80,
|
|
espacioAbajo - separacion
|
|
) + "px";
|
|
}
|
|
|
|
else {
|
|
menu.style.maxHeight =
|
|
Math.max(
|
|
80,
|
|
espacioArriba - separacion
|
|
) + "px";
|
|
|
|
altoMenu = Math.min(
|
|
menu.offsetHeight,
|
|
Math.max(
|
|
80,
|
|
espacioArriba - separacion
|
|
)
|
|
);
|
|
|
|
arriba =
|
|
rectangulo.top -
|
|
altoMenu -
|
|
separacion;
|
|
}
|
|
|
|
/*
|
|
* Alineamos el borde derecho del menú
|
|
* con el borde derecho del botón.
|
|
*/
|
|
var izquierda =
|
|
rectangulo.right -
|
|
anchoMenu;
|
|
|
|
/*
|
|
* Protección del borde izquierdo.
|
|
*/
|
|
if (izquierda < margen) {
|
|
izquierda = margen;
|
|
}
|
|
|
|
/*
|
|
* Protección del borde derecho.
|
|
*/
|
|
if (
|
|
izquierda + anchoMenu >
|
|
anchoVentana - margen
|
|
) {
|
|
izquierda = Math.max(
|
|
margen,
|
|
anchoVentana -
|
|
anchoMenu -
|
|
margen
|
|
);
|
|
}
|
|
|
|
/*
|
|
* Protección vertical.
|
|
*/
|
|
arriba = Math.max(
|
|
margen,
|
|
Math.min(
|
|
arriba,
|
|
altoVentana -
|
|
margen
|
|
)
|
|
);
|
|
|
|
menu.style.left =
|
|
izquierda + "px";
|
|
|
|
/*
|
|
* Reafirmamos right:auto porque Bootstrap
|
|
* puede traer right:0 desde dropdown-menu-right.
|
|
*/
|
|
menu.style.right = "auto";
|
|
|
|
menu.style.top =
|
|
arriba + "px";
|
|
|
|
menu.style.visibility =
|
|
"visible";
|
|
}
|
|
|
|
function abrirMenuAcciones(boton) {
|
|
var contenedor =
|
|
boton.closest(
|
|
".sig-menu-acciones"
|
|
);
|
|
|
|
var formulario =
|
|
obtenerFormulario();
|
|
|
|
var menu;
|
|
|
|
if (
|
|
!contenedor ||
|
|
!formulario
|
|
) {
|
|
return;
|
|
}
|
|
|
|
menu =
|
|
contenedor.querySelector(
|
|
".sig-menu-acciones-lista"
|
|
);
|
|
|
|
if (!menu) {
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Si pulsamos nuevamente el mismo botón,
|
|
* cerramos el menú.
|
|
*/
|
|
if (menuAbierto === menu) {
|
|
cerrarMenuAcciones();
|
|
return;
|
|
}
|
|
|
|
cerrarMenuAcciones();
|
|
|
|
menuAbierto = menu;
|
|
botonMenuAbierto = boton;
|
|
origenMenuAbierto = contenedor;
|
|
|
|
/*
|
|
* Sacamos temporalmente el menú del contenedor
|
|
* que tiene overflow/scroll.
|
|
*
|
|
* Así table-responsive no puede cortarlo.
|
|
*/
|
|
formulario.appendChild(menu);
|
|
|
|
menu.classList.add(
|
|
"sig-menu-acciones-flotante"
|
|
);
|
|
|
|
boton.setAttribute(
|
|
"aria-expanded",
|
|
"true"
|
|
);
|
|
|
|
posicionarMenu(
|
|
menu,
|
|
boton
|
|
);
|
|
}
|
|
|
|
function registrarEventosMenuAcciones() {
|
|
if (eventosMenuRegistrados) {
|
|
return;
|
|
}
|
|
|
|
eventosMenuRegistrados = true;
|
|
|
|
documento.addEventListener(
|
|
"click",
|
|
function (evento) {
|
|
var boton =
|
|
evento.target.closest(
|
|
".sig-menu-acciones-boton"
|
|
);
|
|
|
|
if (boton) {
|
|
evento.preventDefault();
|
|
evento.stopPropagation();
|
|
|
|
abrirMenuAcciones(
|
|
boton
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
if (
|
|
menuAbierto &&
|
|
!evento.target.closest(
|
|
".sig-menu-acciones-lista"
|
|
)
|
|
) {
|
|
cerrarMenuAcciones();
|
|
}
|
|
}
|
|
);
|
|
|
|
documento.addEventListener(
|
|
"sigvisualizadorabierto",
|
|
function (evento) {
|
|
var layout =
|
|
evento.target.closest(
|
|
".sig-documentos-layout"
|
|
);
|
|
|
|
if (!layout) {
|
|
return;
|
|
}
|
|
|
|
layout.classList.add(
|
|
"sig-documentos-visor-activo"
|
|
);
|
|
|
|
layout.classList.remove(
|
|
"sig-documentos-visor-expandido"
|
|
);
|
|
|
|
cerrarMenuAcciones();
|
|
}
|
|
);
|
|
|
|
documento.addEventListener(
|
|
"sigvisualizadorcerrado",
|
|
function (evento) {
|
|
var layout =
|
|
evento.target.closest(
|
|
".sig-documentos-layout"
|
|
);
|
|
|
|
if (!layout) {
|
|
return;
|
|
}
|
|
|
|
layout.classList.remove(
|
|
"sig-documentos-visor-activo"
|
|
);
|
|
|
|
layout.classList.remove(
|
|
"sig-documentos-visor-expandido"
|
|
);
|
|
}
|
|
);
|
|
|
|
documento.addEventListener(
|
|
"sigvisualizadorexpandido",
|
|
function (evento) {
|
|
var layout =
|
|
evento.target.closest(
|
|
".sig-documentos-layout"
|
|
);
|
|
|
|
if (!layout) {
|
|
return;
|
|
}
|
|
|
|
layout.classList.toggle(
|
|
"sig-documentos-visor-expandido",
|
|
!!(
|
|
evento.detail &&
|
|
evento.detail.expandido
|
|
)
|
|
);
|
|
}
|
|
);
|
|
|
|
documento.addEventListener(
|
|
"keydown",
|
|
function (evento) {
|
|
if (evento.key === "Escape") {
|
|
cerrarMenuAcciones();
|
|
}
|
|
}
|
|
);
|
|
|
|
/*
|
|
* Si cambia el scroll, cerramos.
|
|
*
|
|
* Esto evita que el menú flotante quede
|
|
* separado del botón que lo abrió.
|
|
*/
|
|
documento.addEventListener(
|
|
"scroll",
|
|
cerrarMenuAcciones,
|
|
true
|
|
);
|
|
|
|
ventana.addEventListener(
|
|
"resize",
|
|
cerrarMenuAcciones
|
|
);
|
|
|
|
/*
|
|
* Antes de un async postback devolvemos
|
|
* el menú a su lugar original.
|
|
*/
|
|
if (
|
|
ventana.Sys &&
|
|
ventana.Sys.WebForms &&
|
|
ventana.Sys.WebForms.PageRequestManager
|
|
) {
|
|
ventana.Sys.WebForms
|
|
.PageRequestManager
|
|
.getInstance()
|
|
.add_beginRequest(function () {
|
|
cerrarMenuAcciones();
|
|
});
|
|
}
|
|
}
|
|
|
|
function inicializar(raiz) {
|
|
inicializarCortinas(raiz);
|
|
registrarEventosMenuAcciones();
|
|
}
|
|
|
|
if (
|
|
ventana.SIGDocumentosEtapaRegistrado
|
|
) {
|
|
return;
|
|
}
|
|
|
|
ventana.SIGDocumentosEtapaRegistrado =
|
|
true;
|
|
|
|
if (
|
|
documento.readyState === "loading"
|
|
) {
|
|
documento.addEventListener(
|
|
"DOMContentLoaded",
|
|
function () {
|
|
inicializar(
|
|
documento
|
|
);
|
|
}
|
|
);
|
|
} else {
|
|
inicializar(
|
|
documento
|
|
);
|
|
}
|
|
|
|
/*
|
|
* Volver a inicializar después de cada
|
|
* partial postback de WebForms.
|
|
*/
|
|
if (
|
|
ventana.Sys &&
|
|
ventana.Sys.Application
|
|
) {
|
|
ventana.Sys.Application.add_load(
|
|
function () {
|
|
inicializar(
|
|
documento
|
|
);
|
|
}
|
|
);
|
|
}
|
|
|
|
}(window, document)); |