DocManager/doc.manager.html
2025-07-13 20:26:57 +02:00

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>