1124 lines
50 KiB
HTML
1124 lines
50 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="es">
|
|
<head>
|
|
<title data-i18n="doc_manager_title">Doc Manager</title>
|
|
<meta http-equiv="content-type" content="text/html;charset=8" />
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
|
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
|
|
|
<meta name="xdoc:url" content="https://docmanager.k3y.pw/" />
|
|
<meta name="xdoc:git" content="https://git.k3y.pw/KyMAN/DocManager" />
|
|
<meta name="xdoc:author" content="mbruzon" />
|
|
<meta name="xdoc:since" content="20250712" />
|
|
<meta name="xdoc:version" content="20250712" />
|
|
<meta name="xdoc:access" content="public" />
|
|
<meta name="xdoc:license" content="CC-BY-NC-SA 4.0" />
|
|
|
|
<link type="text/css;charset=utf-8" data-language="CSS3" rel="stylesheet" href="https://cdn.k3y.pw/css/FA6F.v6.5.2.remote.css" data-crossorigin="anonymous" charset="utf-8" />
|
|
|
|
<script data-bloque="datos" data-type="text/javascript;charset=utf-8" data-language="ECMAScript 2015" charset="utf-8">
|
|
"use strict";
|
|
|
|
// [NOMBRE, DESCRIPCION, [TAGS], [PATRONES], [LINKS]]
|
|
/** @type {Array.<Object.<string, any|null>>} */
|
|
const DATOS = [];
|
|
|
|
</script>
|
|
|
|
|
|
<script data-bloque="configuracion" data-type="text/javascript;charset=utf-8" data-language="ECMAScript 2015" charset="utf-8">
|
|
"use strict";
|
|
|
|
/** @type {Object.<string, any|null>} */
|
|
const CONFIGURACION = {
|
|
/** @type {string|HTMLElement} */
|
|
posicion : "body",
|
|
/** @type {number} */
|
|
precarga_timeout : 2000,
|
|
/** @type {string} */
|
|
aplicacion_nombre : "DocManager",
|
|
/** @type {string} */
|
|
aplicacion_logo : "DocManager.webp",
|
|
/** @type {string} */
|
|
aplicacion_url : "https://docmanager.k3y.pw/",
|
|
/** @type {string} */
|
|
aplicacion_git : "https://git.k3y.pw/KyMAN/DocManager",
|
|
/** @type {string} */
|
|
aplcacion_id : "doc-manager",
|
|
/** @type {number} */
|
|
celdas : 40,
|
|
/** @type {number} */
|
|
tamano_minimo : 12, // En píxels.
|
|
/** @type {boolean} */
|
|
mostrar_nombre : true,
|
|
/** @type {boolean} */
|
|
mostrar_descripcion : true,
|
|
/** @type {boolean} */
|
|
mostrar_tags : true,
|
|
/** @type {boolean} */
|
|
mostrar_patrones : false,
|
|
/** @type {boolean} */
|
|
mostrar_links : true,
|
|
/** @type {boolean} */
|
|
buscar_en_nombre : true,
|
|
/** @type {boolean} */
|
|
buscar_en_descripcion : true,
|
|
/** @type {boolean} */
|
|
buscar_en_tags : true,
|
|
/** @type {boolean} */
|
|
buscar_en_patrones : true,
|
|
/** @type {boolean} */
|
|
buscar_en_links : false,
|
|
/** @type {Object.<string, any|null>} */
|
|
estilos_css : {
|
|
/** @type {number} */
|
|
tamano_cabecera : 4,
|
|
/** @type {number} */
|
|
tamano_pie : 2,
|
|
/** @type {string} */
|
|
color_fondo : "#FFF",
|
|
/** @type {string} */
|
|
color_frente : "#000",
|
|
/** @type {string} */
|
|
color_gris : "#A7A9AC",
|
|
/** @type {string} */
|
|
color_principal : "#045C8E",
|
|
/** @type {string} */
|
|
color_secundario : "#8E5C04",
|
|
/** @type {string} */
|
|
color_principal_fondo : "rgba(3, 92, 142, 20%)",
|
|
/** @type {string} */
|
|
color_secundario_fondo : "rgba(142, 92, 3, 20%)"
|
|
}
|
|
};
|
|
|
|
</script>
|
|
|
|
<style data-bloque="estilos" data-type="text/css;charset=utf-8" data-language="SASS/CSS3" data-rel="stylesheet" charset="utf-8">
|
|
|
|
html,body{
|
|
height : 100%;
|
|
margin : 0px;
|
|
}
|
|
|
|
</style>
|
|
|
|
<script data-bloque="generador-estilos" data-type="text/javascript;charset=utf-8" data-language="ECMAScript 2015" charset="utf-8">
|
|
"use strict";
|
|
|
|
/** @type {number} */
|
|
let precargador_del_generador_de_estilos = setInterval(() => {
|
|
if(DocManager && DocManager.anadir_css){
|
|
clearInterval(precargador_del_generador_de_estilos);
|
|
|
|
/** @type {Object.<string, any|null>} */
|
|
const $ = CONFIGURACION.estilos_css;
|
|
|
|
DocManager.anadir_css({
|
|
|
|
".doc-manager" : {
|
|
|
|
position : "relative",
|
|
top : "0em",
|
|
left : "0em",
|
|
width : "100%",
|
|
height : "100%",
|
|
|
|
"a[href],button" : {
|
|
color : $.color_principal,
|
|
cursor : "pointer",
|
|
"transition-duration" : "1s",
|
|
"&:hover" : {
|
|
color : $.color_secundario,
|
|
"transition-duration" : ".35s"
|
|
}
|
|
},
|
|
"a[href]" : {
|
|
"text-decoration" : null,
|
|
"transition-property" : "color"
|
|
},
|
|
button : {
|
|
border : ".1em solid " + $.color_principal,
|
|
"background-color" : $.color_principal_fondo,
|
|
"border-radius" : ".3em",
|
|
"box-shadow" : "0em 0em .4em inset " + $.color_principal,
|
|
"transition-property" : "color,border-color,box-shadow,background-color,opacity",
|
|
"&:hover" : {
|
|
"border-color" : $.color_secundario,
|
|
"background-color" : $.color_secundario_fondo,
|
|
"box-shadow" : "0em 0em .4em inset " + $.color_secundario_fondo,
|
|
},
|
|
"&[data-activo=false]" : {opacity : .5}
|
|
},
|
|
|
|
"[data-icon]::before" : {
|
|
"margin-right" : ".4em",
|
|
"font-family" : "FA6FS"
|
|
},
|
|
|
|
"header,main,footer" : {
|
|
position : "absolute",
|
|
left : "0em",
|
|
width : "100%"
|
|
},
|
|
header : {
|
|
top : "0em",
|
|
height : $.tamano_cabecera + "em",
|
|
"z-index" : 20
|
|
},
|
|
main : {
|
|
top : $.tamano_cabecera + "em",
|
|
bottom : $.tamano_pie + "em",
|
|
"z-index" : 10,
|
|
overflow : "hidden"
|
|
},
|
|
footer : {
|
|
bottom : "0em",
|
|
height : $.tamano_pie + "em",
|
|
"z-index" : 30
|
|
},
|
|
|
|
h1 : {
|
|
margin : "0em",
|
|
padding : "0em",
|
|
"font-size" : "1em",
|
|
img : {
|
|
"padding" : "0em 1em",
|
|
width : "auto",
|
|
height : ($.tamano_cabecera - .4) + "em",
|
|
"&+span" : {display : null}
|
|
},
|
|
".titulo" : {
|
|
"font-size" : $.tamano_cabecera + "em",
|
|
"font-weight" : 900
|
|
},
|
|
"a>span" : {
|
|
"padding-top" : ".2em",
|
|
"vertical-align" : "middle"
|
|
}
|
|
},
|
|
|
|
form : {
|
|
div : {
|
|
display : "table",
|
|
width : "80%",
|
|
"white-space" : "nowrap",
|
|
"&>*" : {display : "table-cell"},
|
|
input : {width : "100%"},
|
|
"[data-icon]" : {
|
|
"&::before" : {margin : "0em"},
|
|
"&+[data-i18n]" : {display : null}
|
|
}
|
|
},
|
|
"[data-opcion]>button" : {
|
|
"[data-icon]::before" : {margin : "0em"},
|
|
"[data-i18n]" : {display : null}
|
|
}
|
|
},
|
|
|
|
"[data-nombre=false] [data-campo=nombre]" : {display : null},
|
|
"[data-descripcion=false] [data-campo=descripcion]" : {display : null},
|
|
"[data-tags=false] [data-campo=tags]" : {display : null},
|
|
"[data-patrones=false] [data-campo=patrones]" : {display : null},
|
|
"[data-links=false] [data-campo=links]" : {display : null},
|
|
|
|
".licencias" : {
|
|
"font-size" : ".85em",
|
|
"font-weight" : 900,
|
|
"text-align" : "center",
|
|
img : {
|
|
width : "auto",
|
|
height : "1em"
|
|
}
|
|
},
|
|
|
|
"[data-icon=buscar]::before" : {content : '"\\f002"'},
|
|
"[data-icon=autobuscar]::before" : {content : '"\\f3eb"', "font-family" : "FA6FB"},
|
|
"[data-icon=case_sensitive]::before" : {content : '"\\f034"'},
|
|
"[data-activo=true]>[data-icon=visible]::before" : {content : '"\\f06e"'},
|
|
"[data-activo=false]>[data-icon=visible]::before" : {content : '"\\f070"'},
|
|
"[data-activo=true]>[data-icon=en_uso]::before" : {content : '"\\f205"'},
|
|
"[data-activo=false]>[data-icon=en_uso]::before" : {content : '"\\f204"'}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
}, 10);
|
|
|
|
</script>
|
|
|
|
<script data-bloque="script" data-type="text/javascript;charset=utf-8" data-language="ECMAScript 2015" charset="utf-8">
|
|
"use strict";
|
|
|
|
/**
|
|
* @class
|
|
* @constructor
|
|
* @param {!(Object.<string, any|null>|Array.<any|null>)} [personalizado = null]
|
|
* @returns {void}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
const DocManager = (function(){
|
|
|
|
/**
|
|
* @callback doc_manager_callback_por_defecto
|
|
* @returns {void}
|
|
*/
|
|
|
|
/**
|
|
* @callback doc_manager_ejecutar_callback
|
|
* @param {...(any|null)} [parameters]
|
|
* @returns {any|null}
|
|
*/
|
|
|
|
/**
|
|
* @callback doc_manager_precargar_callback
|
|
* @param {?HTMLElement} elemento
|
|
* @param {!boolean} asincrono
|
|
* @param {!number} error
|
|
* @returns {void}
|
|
*/
|
|
|
|
/**
|
|
* @callback doc_manager_evento_callback
|
|
* @param {!HTMLElement} elemento
|
|
* @param {!Event} evento
|
|
* @returns {any|null}
|
|
*/
|
|
|
|
/**
|
|
* @constructs DocManager
|
|
* @param {!(Object.<string, any|null>|Array.<any|null>)} [personalizado = null]
|
|
* @returns {void}
|
|
* @access private
|
|
* @static
|
|
*/
|
|
const DocManager = function(personalizado = null){
|
|
|
|
/** @type {DocManager} */
|
|
const self = this,
|
|
/** @type {Object.<string, number>} */
|
|
pantalla = {x : 0, y : 0};
|
|
/** @type {number|null} */
|
|
let pantalla_intervalo = null,
|
|
/** @type {number} */
|
|
celdas = 40,
|
|
/** @type {number} */
|
|
tamano_minimo = 12;
|
|
|
|
/** @type {number} */
|
|
this.precarga_timeout = 2000;
|
|
/** @type {string} */
|
|
this.aplicacion_nombre = "DocManager";
|
|
/** @type {string} */
|
|
this.aplicacion_logo = "DocManager.webp";
|
|
/** @type {string} */
|
|
this.aplicacion_url = "http://docmanager.k3y.pw/";
|
|
/** @type {string} */
|
|
this.aplicacion_git = "https://git.k3y.pw/KyMAN/DocManager";
|
|
/** @type {string} */
|
|
this.aplicacion_id = "doc-manager";
|
|
|
|
/** @type {HTMLElement|null} */
|
|
this.item_self = null;
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const constructor = () => {
|
|
|
|
self.precarga_timeout = self.coger_valor(["precarga_timeout", "timeout"], null, self.precarga_timeout);
|
|
["nombre", "logo", "url", "git", "id"].forEach(clave => {
|
|
self["aplicacion_" + clave] = self.coger_valor(["aplicacion_" + clave, clave], null, self["aplicacion_" + clave]);
|
|
});
|
|
celdas = self.coger_valor("celdas");
|
|
tamano_minimo = self.coger_valor("tamano_minimo");
|
|
|
|
DocManager.precargar(self.coger_valor("posicion"), (posicion, asincrono, error) => {
|
|
if(!error){
|
|
|
|
/** @type {Array.<any>} */
|
|
const cabecera = [
|
|
["tr", null, DocManager.CAMPOS.map(([clave, texto]) => ["th", {data_campo : clave, data_i18n : clave}, texto])]
|
|
],
|
|
/** @type {Object.<string, boolean>} */
|
|
campos = {};
|
|
|
|
DocManager.CAMPOS.forEach(([clave, _]) => {
|
|
["mostrar", "buscar_en"].forEach(accion => {
|
|
campos[accion + "_" + clave] = self.coger_valor(accion + "_" + clave);
|
|
});
|
|
});
|
|
|
|
self.item_self = DocManager.establecer_html([
|
|
["div", {
|
|
id : self.aplicacion_id,
|
|
class : self.aplicacion_id,
|
|
data_application : self.aplicacion_nombre,
|
|
data_git : self.aplicacion_git,
|
|
data_url : self.aplicacion_url,
|
|
data_celdas : celdas,
|
|
data_tamano_minimo : tamano_minimo
|
|
}, [
|
|
["header", null, [
|
|
["h1", {class : "logo", title : self.aplicacion_nombre}, [
|
|
["a", {href : self.aplicacion_url, target : "_self"}, [
|
|
["span", {class : "imagen"}, [
|
|
["img", {src : self.aplicacion_logo, alt : self.aplicacion_nombre}],
|
|
["span", {style : "background-image:url('" + self.aplicacion_logo + "');"}]
|
|
]],
|
|
["span", {class : "titulo"}, self.aplicacion_nombre]
|
|
]]
|
|
]]
|
|
]],
|
|
["main", null, [
|
|
["form", {method : "GET", action : "#", on_submit : (elemento, evento) => false}, [
|
|
["fieldset", null, [
|
|
["legend", {data_i18n : "filtrar"}, "Filtrar"],
|
|
["p", {data_i18n : "filtrar_descripcion"}, "Para buscar contenido por favor, escribe qué necesitas, y si es necesario, escribe algún patrón de búsqueda."],
|
|
["div", null, [
|
|
["label", {for : "buscar"}, "Buscar"],
|
|
["input", {type : "text", name : "buscar", id : "buscar", data_i18n : "buscar", data_i18n_without : true, placeholder : "Buscar..."}],
|
|
DocManager.toggle("case_sensitive", false, null, "Diferenciar mayúsculas de minísculas"),
|
|
DocManager.toggle("autobuscar", true, null, "Búsqueda automática"),
|
|
DocManager.boton("buscar", buscar, "Buscar")
|
|
]],
|
|
["p", {data_i18n : "opcions_filtro"}, "Opciones de visibilidad y uso en filtro de búsqueda."],
|
|
["nav", null, [
|
|
["ul", null, DocManager.CAMPOS.map(([clave, texto]) => DocManager.opcion(
|
|
clave,
|
|
campos["mostrar_" + clave],
|
|
campos["buscar_en_" + clave],
|
|
texto,
|
|
cambiar_visibilidad
|
|
))]
|
|
]]
|
|
]]
|
|
]],
|
|
["fieldset", {class : "contenidos"}, [
|
|
["legend", {data_i18n : "contenidos"}, "Contenidos"],
|
|
["p", {data_i18n : "contenidos_descripcion"}, "A continuación se mostrarán los contenidos para que puedan ser tratados para gestionar la búsqueda y filtros correspondientes."],
|
|
["table", DocManager.CAMPOS.reduce((diccionario, [clave, _]) => ({...diccionario, ["data-" + clave] : campos["mostrar_" + clave]}), {}), [
|
|
["thead", null, cabecera],
|
|
["tbody"],
|
|
["tfoot", null, cabecera]
|
|
]]
|
|
]]
|
|
]],
|
|
["footer", null, [
|
|
["div", {class : "licencias"}, [
|
|
["span", {class : "copyright", title : "© 2025-2026 Copyright. Concello de Ferrol."}, [
|
|
"© 2025-2026 Copyright. ",
|
|
["a", {href : "https://ferrol.gal/", target : "_blank"}, "Concello de Ferrol"],
|
|
"."
|
|
]],
|
|
["a", {
|
|
class : "creative-commons",
|
|
href : "https://creativecommons.org/licenses/by-nc-sa/4.0/",
|
|
target : "_blank",
|
|
title : "Creative Commons BY-NC-SA 4.0. Atribución, no Comercial, Compartir Permitido."
|
|
}, [
|
|
"Creative Commons BY-NC-SA 4.0. Atribución, no Comercial, Compartir Permitido.",
|
|
["img", {
|
|
src : "https://upload.wikimedia.org/wikipedia/commons/4/4b/CC_BY-NC-SA.svg",
|
|
alt : "Creative Commons BY-NC-SA 4.0"
|
|
}]
|
|
]]
|
|
]]
|
|
]]
|
|
]]
|
|
], posicion)[0];
|
|
pantalla_intervalo = setInterval(pantalla_hilo, 100);
|
|
|
|
};
|
|
}, self.precarga_timeout);
|
|
|
|
};
|
|
|
|
/**
|
|
* @param {!(string|Array.<string>)} claves
|
|
* @param {?(Object.<string, any|null>|Array.<any|null>)} [entradas = null]
|
|
* @param {?any} [por_defecto = null]
|
|
* @returns {any|null}
|
|
* @access public
|
|
*/
|
|
this.coger_valor = (claves, entradas = null, por_defecto = null) => DocManager.coger_valor(claves, [
|
|
entradas, personalizado, CONFIGURACION
|
|
], por_defecto);
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const pantalla_hilo = () => {
|
|
if(pantalla.x != self.item_self.offsetWidth || pantalla.y != self.item_self.offsetHeight){
|
|
|
|
/** @type {number} */
|
|
let tamano;
|
|
|
|
pantalla.x = self.item_self.offsetWidth;
|
|
pantalla.y = self.item_self.offsetHeight;
|
|
|
|
tamano = pantalla[pantalla.x < pantalla.y ? "x" : "y"] / celdas;
|
|
|
|
self.item_self.style.fontSize = (tamano < tamano_minimo ? tamano_minimo : tamano) + "px";
|
|
|
|
};
|
|
};
|
|
|
|
/**
|
|
* @param {!HTMLElement} elemento
|
|
* @param {!Event} evento
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const cambiar_visibilidad = (elemento, evento) => {
|
|
self.item_self.querySelector(".contenidos table").setAttribute("data-" + elemento.parentNode.getAttribute("data-opcion"), elemento.getAttribute("data-activo"));
|
|
};
|
|
|
|
/**
|
|
* @param {HTMLElement} elemento
|
|
* @param {Event} evento
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const buscar = (elemento, evento) => {
|
|
console.log("BUSCAR");
|
|
};
|
|
|
|
constructor();
|
|
|
|
};
|
|
|
|
/** @type {Array.<[string, string]>} */
|
|
DocManager.CAMPOS = [
|
|
["nombre", "Nombre"],
|
|
["descripcion", "descripcion"],
|
|
["tags", "Tags"],
|
|
["patrones", "Patrones"],
|
|
["links", "links"]
|
|
];
|
|
|
|
/**
|
|
* @param {?any} elemento
|
|
* @returns {boolean}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.es_string = elemento => typeof elemento == "string";
|
|
|
|
/**
|
|
* @param {?any} elemento
|
|
* @returns {boolean}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.es_clave = elemento => DocManager.es_string(elemento) && (elemento = elemento.trim()) && /^[a-z_][a-z0-9_]*$/i.test(elemento);
|
|
|
|
/**
|
|
* @param {?any} elemento
|
|
* @returns {boolean}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.es_numero = elemento => typeof elemento == "number";
|
|
|
|
/**
|
|
* @param {?any} elemento
|
|
* @returns {boolean}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.es_entero = elemento => DocManager.es_numero(elemento) && elemento == elemento >> 0;
|
|
|
|
/**
|
|
* @param {?any} elemento
|
|
* @returns {boolean}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.es_positivo = elemento => DocManager.es_numero(elemento) && elemento >= 0;
|
|
|
|
/**
|
|
* @param {?any} elemento
|
|
* @returns {boolean}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.es_funcion = elemento => typeof elemento == "function";
|
|
|
|
/**
|
|
* @param {?any} elemento
|
|
* @returns {boolean}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.es_diccionario = elemento => elemento && elemento.constructor == Object;
|
|
|
|
/**
|
|
* @param {?any} elemento
|
|
* @param {!boolean} [lista_de_nodos = false]
|
|
* @returns {boolean}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.es_array = (elemento, lista_de_nodos = false) => (
|
|
elemento instanceof Array ||
|
|
(lista_de_nodos && elemento instanceof NodeList)
|
|
);
|
|
|
|
/**
|
|
* @param {?any} elemento
|
|
* @returns {boolean}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.es_elemento_html = elemento => elemento && (elemento.tagName || elemento.nodeName);
|
|
|
|
/**
|
|
* @param {?any} bloque
|
|
* @returns {Array.<any|null>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.coger_array = bloque => (
|
|
DocManager.es_array(bloque) ? bloque :
|
|
DocManager.es_array(bloque, true) ? [...bloque] :
|
|
[bloque]);
|
|
|
|
/**
|
|
* @param {?any} nodos
|
|
* @returns {Array.<HTMLElement}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.listar_nodos = (...nodos) => nodos.reduce((nodos, nodo) => {
|
|
|
|
if(DocManager.es_array(nodo))
|
|
nodos.push(...(DocManager.es_array(nodo, true) ? [...nodo] : DocManager.listar_nodos(...nodo)));
|
|
else if(DocManager.es_elemento_html(nodo))
|
|
nodos.push(nodo);
|
|
|
|
return nodos;
|
|
}, []);
|
|
|
|
/**
|
|
* @param {...(any|null)} claves
|
|
* @returns {Array.<string>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.coger_claves = (...claves) => claves.reduce((claves, elemento) => {
|
|
|
|
if(DocManager.es_clave(elemento))
|
|
claves.push(elemento);
|
|
else if(DocManager.es_array(elemento))
|
|
claves.push(...DocManager.coger_claves(...elemento));
|
|
|
|
return claves;
|
|
}, []);
|
|
|
|
/**
|
|
* @param {...(any|null)} diccionarios
|
|
* @returns {Array.<Object.<string, any|null>>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.coger_diccionarios = (...diccionarios) => diccionarios.reduce((diccionarios, elemento) => {
|
|
|
|
if(DocManager.es_diccionario(elemento))
|
|
diccionarios.push(elemento);
|
|
else if(DocManager.es_array(elemento))
|
|
diccionarios.push(...DocManager.coger_diccionarios(...elemento));
|
|
|
|
return diccionarios;
|
|
}, []);
|
|
|
|
/**
|
|
* @param {!(Object.<string, any|null>|Array.<any|null>)} diccionarios
|
|
* @param {!boolean} [sobreescribir = false]
|
|
* @returns {Object.<string, any|null>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.coger_diccionario = (diccionarios, sobrreescribir = false) => DocManager.coger_diccionarios(diccionarios).reduce((conjunto, diccionario) => {
|
|
|
|
for(const clave in diccionario)
|
|
(sobrreescribir || conjunto[clave] === undefined) && (conjunto[clave] = diccionario[clave]);
|
|
|
|
return diccionario;
|
|
}, {});
|
|
|
|
/**
|
|
* @param {!(string|Array.<string>)} claves
|
|
* @param {!(Object.<string, any|null>|Array.<any|null>)} entradas
|
|
* @param {?any} [por_defecto = null]
|
|
* @returns {any|null}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.coger_valor = (claves, entradas, por_defecto = null) => {
|
|
|
|
/** @type {[number, number]} */
|
|
const [l, m] = [
|
|
(entradas = DocManager.coger_diccionarios(entradas)).length,
|
|
(claves = DocManager.coger_claves(claves)).length
|
|
];
|
|
|
|
if(l && m){
|
|
for(let i = 0; i < l; i ++)
|
|
for(let j = 0; j < m; j ++)
|
|
if(entradas[i][claves[j]] !== undefined)
|
|
return entradas[i][claves[j]];
|
|
};
|
|
return por_defecto;
|
|
};
|
|
|
|
/**
|
|
* @param {!doc_manager_ejecutar_callback}
|
|
* @param {...(any|null)} [parameters]
|
|
* @returns {any|null}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.ejecutar = (callback, ...parametros) => DocManager.es_funcion(callback) ? callback(...parametros) : null;
|
|
|
|
/**
|
|
* @param {!(string|HTMLElement)} selector
|
|
* @param {!doc_manager_precargar_callback} callback
|
|
* @param {!number} [timeout = 2000]
|
|
* @returns {[HTMLElement|null, boolean, number]}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.precargar = (selector, callback, timeout = 2000) => {
|
|
|
|
/** @type {number} */
|
|
let error = (
|
|
((
|
|
selector === undefined ? 1 << 0 :
|
|
selector === null ? 1 << 1 :
|
|
0) << 0) |
|
|
((
|
|
callback === undefined ? 1 << 0 :
|
|
callback === null ? 1 << 1 :
|
|
!DocManager.es_funcion(callback) ? 1 << 2 :
|
|
0) << 4) |
|
|
((
|
|
timeout === undefined ? 1 << 0 :
|
|
timeout === null ? 1 << 1 :
|
|
!DocManager.es_numero(timeout) ? 1 << 2 :
|
|
!DocManager.es_entero(timeout) ? 1 << 3 :
|
|
!DocManager.es_positivo(timeout) ? 1 << 4 :
|
|
0) << 7) |
|
|
0) << 1,
|
|
/** @type {HTMLElement|null} */
|
|
elemento = null,
|
|
/** @type {boolean} */
|
|
asincrono = false;
|
|
/** @type {doc_manager_callback_por_defecto} */
|
|
const terminar = () => {
|
|
DocManager.ejecutar(callback, elemento, asincrono, error);
|
|
};
|
|
|
|
if(error)
|
|
terminar();
|
|
else{
|
|
if(DocManager.es_elemento_html(selector)){
|
|
elemento = selector;
|
|
terminar();
|
|
}else if(DocManager.es_string(selector)){
|
|
|
|
try{
|
|
(elemento = document.querySelector(selector)) &&
|
|
terminar();
|
|
}catch(excepcion){
|
|
console.error(excepcion);
|
|
error |= 1 << 0;
|
|
terminar();
|
|
};
|
|
|
|
if(asincrono = !error && !elemento){
|
|
|
|
/** @type {number} */
|
|
const fecha = Date.now();
|
|
/** @type {number} */
|
|
let intervalo = setInterval(() => {
|
|
if(elemento = document.querySelector(selector)){
|
|
clearInterval(intervalo);
|
|
terminar();
|
|
}else if(Date.now() - fecha > timeout){
|
|
clearInterval(intervalo);
|
|
error |= 1 << 4
|
|
terminar();
|
|
};
|
|
}, 100);
|
|
};
|
|
|
|
}else{
|
|
error |= 1 << 3
|
|
terminar();
|
|
};
|
|
};
|
|
|
|
return [elemento, asincrono, error];
|
|
};
|
|
|
|
/**
|
|
* @param {!string} string
|
|
* @returns {string}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.snake_a_kebab = string => string.replace(/_/g, "-");
|
|
|
|
/**
|
|
* @param {Object.<string, any|null>} atributos
|
|
* @param {?(HTMLElement|NodeList|Array.<HTMLElement>)} [elementos = null]
|
|
* @returns {string|null}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.establecer_atributos = (atributos, elementos = null) => {
|
|
|
|
/** @type {string|null} */
|
|
let html = null;
|
|
|
|
atributos = DocManager.coger_diccionario(atributos);
|
|
if(elementos)
|
|
DocManager.listar_nodos(elementos).forEach(elemento => {
|
|
for(const nombre in atributos){
|
|
if(/^on_?/i.test(nombre) && DocManager.es_funcion(atributos[nombre]))
|
|
elemento.addEventListener(nombre.replace(/^on_?/i, ""), evento => atributos[nombre](elemento, evento));
|
|
else
|
|
elemento.setAttribute(DocManager.snake_a_kebab(nombre), atributos[nombre]);
|
|
};
|
|
});
|
|
else{
|
|
html = ``;
|
|
for(const nombre in atributos){
|
|
if(/^on_?/i.test(nombre) && DocManager.es_funcion(atributos[nombre])){
|
|
// Montar sistema por Hash identificativo.
|
|
}else
|
|
html += ` ` + DocManager.snake_a_kebab(nombre) + `="` + atributos[nombre] + `"`;
|
|
};
|
|
};
|
|
|
|
return html;
|
|
};
|
|
|
|
/**
|
|
* @param {Array.<[string, Object.<string, any|null>|null, Array.<any>|null>]} estructura
|
|
* @param {?HTMLElement} [posicion = null]
|
|
* @returns {Array.<HTMLElement>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.establecer_html = (estructura, posicion = null) => {
|
|
|
|
/** @type {Array.<HTMLElement>} */
|
|
const elementos = [];
|
|
|
|
if(DocManager.es_array(estructura))
|
|
estructura.forEach(hijo => {
|
|
if(DocManager.es_string(hijo))
|
|
posicion && (posicion.innerHTML += hijo);
|
|
else{
|
|
|
|
/** @type {[string, Object.<string, any|null>|null, Array.<any>|null>]} */
|
|
const [tag, atributos, hijos] = hijo.concat(null, null), /** @type {HTMLElement} */
|
|
/** @type {HTMLElement} */
|
|
elemento = document.createElement(tag);
|
|
|
|
atributos && DocManager.establecer_atributos(atributos, elemento);
|
|
hijos && DocManager.establecer_html(hijos, elemento);
|
|
|
|
elementos.push(elemento);
|
|
posicion && posicion.appendChild(elemento);
|
|
|
|
};
|
|
});
|
|
else
|
|
posicion && (posicion.innerHTML = estructura);
|
|
|
|
return elementos;
|
|
};
|
|
|
|
/**
|
|
* @param {!string} nombre
|
|
* @param {!boolean} activo
|
|
* @param {!doc_manager_evento_callback} accion
|
|
* @param {!string} texto
|
|
* @returns {Array.<any>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.toggle = (nombre, activo, accion, texto) => ["button", {
|
|
type : "button",
|
|
data_activo : activo,
|
|
data_i18n : nombre,
|
|
data_i18n_without : true,
|
|
title : texto,
|
|
on_click : (elemento, evento) => {
|
|
elemento.setAttribute("data-activo", elemento.getAttribute("data-activo") != "true");
|
|
DocManager.ejecutar(accion, elemento, evento);
|
|
}
|
|
}, [
|
|
["span", {data_icon : nombre}],
|
|
["span", {data_i18n : nombre}, texto]
|
|
]];
|
|
|
|
/**
|
|
* @param {!string} nombre
|
|
* @param {!doc_manager_evento_callback} accion
|
|
* @param {!string} texto
|
|
* @returns {Array.<any>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.boton = (nombre, accion, texto, tipo = "button") => ["button", {
|
|
type : tipo,
|
|
data_i18n : nombre,
|
|
data_i18n_without : true,
|
|
title : texto,
|
|
on_click : accion
|
|
}, [
|
|
["span", {data_icon : nombre}],
|
|
["span", {data_i18n : nombre}, texto]
|
|
]];
|
|
|
|
/**
|
|
* @param {!string} nombre
|
|
* @param {!boolean} visible
|
|
* @param {!boolean} en_uso
|
|
* @param {!string} texto
|
|
* @param {?Event} [evento_visible = null]
|
|
* @returns {Array.<any>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.opcion = (nombre, visible, en_uso, texto, evento_visible = null) => ["li", {data_opcion : nombre}, [
|
|
DocManager.toggle("visible", visible, evento_visible, "Visible"),
|
|
DocManager.toggle("en_uso", en_uso, null, "En uso"),
|
|
["span", {data_i18n : nombre}, texto]
|
|
]];
|
|
|
|
/**
|
|
* @param {!string} base
|
|
* @param {!(string|Array.<string>)} fragmentos
|
|
* @returns {Array.<string>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.css_fragmentos_de_selector = (base, fragmentos) => (
|
|
DocManager.es_array(fragmentos) ? fragmentos : fragmentos.split(",")
|
|
).map(fragmento => base + (
|
|
fragmento ? (
|
|
fragmento = fragmento.trim()
|
|
)[0] == '&' ? "" + fragmento.substring(1, fragmento.length) : " " + fragmento :
|
|
""));
|
|
|
|
/**
|
|
* @param {...string} selectores
|
|
* @returns {Array.<string>}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.css_selectores = (...selectores) => selectores.reduce((selectores, fragmento) => {
|
|
|
|
/** @type {Array.<string>} */
|
|
const resultados = [];
|
|
|
|
if(selectores.length)
|
|
selectores.forEach(selector => {
|
|
resultados.push(...DocManager.css_fragmentos_de_selector(selector, fragmento));
|
|
});
|
|
else
|
|
resultados.push(...DocManager.css_fragmentos_de_selector("", fragmento));
|
|
|
|
return resultados;
|
|
}).map(selector => selector.trim());
|
|
|
|
/**
|
|
* @param {!Object.<string, any|null>} atributos
|
|
* @param {!Array.<string>} selectores
|
|
* @returns {string}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.css_bloque = (atributos, selectores) => {
|
|
|
|
/** @type {string} */
|
|
let subbloques = "",
|
|
/** @type {string} */
|
|
bloque = "";
|
|
|
|
for(const nombre in atributos)
|
|
if(DocManager.es_diccionario(atributos[nombre]))
|
|
subbloques += DocManager.css_bloque(atributos[nombre], DocManager.css_selectores(selectores, nombre));
|
|
else
|
|
bloque += "\n\t" + nombre + " : " + (
|
|
DocManager.es_array(atributos[nombre]) ? (
|
|
atributos[nombre].length < 2 ? atributos[nombre][0] :
|
|
"\n\t\t" + atributos[nombre].join(", \n\t\t")) :
|
|
atributos[nombre] === null ? "none" :
|
|
atributos[nombre]) + ";";
|
|
|
|
return selectores.reduce((selector, subselector, i) => (i ? selector + ",\n" : "") + subselector, "")+ "{" + bloque + "\n}\n\n" + subbloques;
|
|
};
|
|
|
|
/**
|
|
* @param {!Object.<string, any|null>} atributos
|
|
* @param {!Array.<string>} [base = []]
|
|
* @returns {string}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.css = (atributos, bases = []) => {
|
|
|
|
/** @type {string} */
|
|
let css = ``;
|
|
|
|
for(const selector in atributos)
|
|
css += DocManager.css_bloque(atributos[selector], DocManager.css_selectores(bases, selector));
|
|
|
|
return css.trim();
|
|
};
|
|
|
|
/**
|
|
* @param {!Object.<string, any|null>} css
|
|
* @returns {void}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
DocManager.anadir_css = css => {
|
|
|
|
/** @type {HTMLStyleElement|null} */
|
|
let elemento = document.querySelector("head>style");
|
|
|
|
if(!elemento){
|
|
elemento = document.querySelector("head").appendChild(document.createElement("style"));
|
|
[
|
|
["data-bloque", "generador-estilos"],
|
|
["data-type", "text/javascript;charset=utf-8"],
|
|
["data-language", "ECMAScript 2015"],
|
|
["charset", "utf-8"]
|
|
].forEach(([clave, valor]) => {
|
|
elemento.setAttribute(clave, valor);
|
|
});
|
|
};
|
|
|
|
elemento.appendChild(document.createTextNode(DocManager.css(css)));
|
|
|
|
};
|
|
|
|
return DocManager;
|
|
})();
|
|
|
|
</script>
|
|
|
|
<script data-bloque="inicializador" data-type="text/javascript;charset=utf-8" data-language="ECMAScript 2015" charset="utf-8">
|
|
"use strict";
|
|
|
|
const doc_manager = new DocManager();
|
|
|
|
</script>
|
|
|
|
</head>
|
|
<body></body>
|
|
<!--
|
|
|
|
GameJam Doc Manager
|
|
|
|
Primer Round
|
|
Objetivos:
|
|
- Crear GUI Web de búsqueda de enlaces por contenido.
|
|
- Gestión por nombre y/o título.
|
|
- Gestión por descripción.
|
|
- Gestión por Tags.
|
|
- Dinámico en caliente.
|
|
- OnePage.
|
|
- JSDoc completado.
|
|
- Código estructurado.
|
|
- Tags con atributos completos.
|
|
- Atributos "data-" implementados.
|
|
- Gestión de errores.
|
|
- Sistema de gestión de configuración.
|
|
- Separación de bloques para facilitar la gestión del proyecto.
|
|
Inicio: 12/07/2025 10:00
|
|
Fin: 12/07/2025 11:00
|
|
Objetivos alcanzados:
|
|
- OnePage.
|
|
- JSDoc completado.
|
|
- Código estructurado.
|
|
- Tags con atributos completos.
|
|
- Atributos "data-" implementados.
|
|
- Gestión de errores.
|
|
- Sistema de gestión de configuración.
|
|
- Separación de bloques para facilitar la gestión del proyecto.
|
|
|
|
Segundo Round
|
|
Objetivos:
|
|
- Crear GUI Web de búsqueda de enlaces por contenido.
|
|
- Gestión por nombre y/o título.
|
|
- Gestión por descripción.
|
|
- Gestión por Tags.
|
|
- Dinámico en caliente.
|
|
- Estructurar la creación de componentes gráficos.
|
|
- Integrar SASS contra CSS compacto.
|
|
Inicio: 12/07/2025 11:05
|
|
Fin: 12/07/2025 11:35
|
|
Objetivos alcanzados:
|
|
- Estructurar la creación de componentes gráficos.
|
|
|
|
Tercer Round
|
|
Objetivos:
|
|
- Crear GUI Web de búsqueda de enlaces por contenido.
|
|
- Gestión por nombre y/o título.
|
|
- Gestión por descripción.
|
|
- Gestión por Tags.
|
|
- Gestión por patrones.
|
|
- Dinámico en caliente.
|
|
- Estructurar la creación de componentes gráficos.
|
|
- Integrar SASS contra CSS compacto.
|
|
- Estructurar información en los DATOS.
|
|
- Crear logo y diseño visual.
|
|
- Estructurar licencia Free OpenSource CC.
|
|
- Iconificar.
|
|
Inicio: 12/07/2025 13:00
|
|
Fin: 12/07/2025 14:00
|
|
Objetivos alcanzados:
|
|
- Crear GUI Web de búsqueda de enlaces por contenido.
|
|
- Estructurar la creación de componentes gráficos.
|
|
- Estructurar información en los DATOS.
|
|
- Crear logo y diseño visual.
|
|
- Estructurar licencia Free OpenSource CC.
|
|
|
|
Cuarto Round
|
|
Objetivos:
|
|
- Crear GUI Web de búsqueda de enlaces por contenido.
|
|
- Gestión por nombre y/o título.
|
|
- Gestión por descripción.
|
|
- Gestión por Tags.
|
|
- Gestión por patrones.
|
|
- Dinámico en caliente.
|
|
- Integrar SASS contra CSS compacto.
|
|
- Diseño visual.
|
|
- Iconificar.
|
|
- Montar sistema de simulación de DPIs.
|
|
- Montar sistema de I18N.
|
|
Inicio: 13/07/2025 09:40
|
|
Fin: 13/07/2025 12:10
|
|
Objetivos alcanzados:
|
|
- Crear GUI Web de búsqueda de enlaces por contenido.
|
|
- Iconificar.
|
|
- Diseño visual.
|
|
- Montar sistema de simulación de DPIs.
|
|
- Integrar SASS contra CSS compacto.
|
|
|
|
-->
|
|
</html> |