Inyección de estilos CSS propios, código JavaScript y botones de acción en cualquier página
JustZix permite inyectar automáticamente tu propio CSS y JavaScript en páginas seleccionadas, así como definir botones de acción (atajos que ejecutan fragmentos de código bajo demanda).
https://justzix.com/*. Puedes habilitar/deshabilitar todo el directorio con un solo clic.Cada conjunto y cada grupo puede tener su propia lista de patrones de URL adicionales (chip-input). Cuando la lista está vacía, el elemento funciona en todos los lugares donde coincida el patrón del directorio. Cuando estableces, por ejemplo, https://justzix.com/admin/*, el elemento solo funcionará en las subpáginas del admin.
| Patrón del directorio | Patrones del conjunto | Funcionará en |
|---|---|---|
https://justzix.com/* | (vacío) | todo el dominio justzix.com |
https://justzix.com/* | https://justzix.com/admin/* | solo la sección /admin/ |
https://justzix.com/* | https://justzix.com/produkty/*https://justzix.com/koszyk | solo las subpáginas de productos + carrito |
*://localhost:*/* | *://localhost:3000/* | solo el puerto 3000 (dev) |
Para los usuarios nuevos, JustZix incluye un tutorial interactivo que te guía paso a paso en la creación de una solución completa — desde una carpeta, pasando por un grupo y un conjunto de reglas, hasta el código CSS/JS y un botón de acción. Las indicaciones aparecen como globos junto a los sucesivos elementos del panel.
Cómo iniciarlo:
En la ventana «Centro de tutoriales» eliges un tutorial y haces clic en Empezar. Durante el tutorial:
Acceso mediante clic derecho sobre el icono de la extensión → "Opciones", o clic sobre el icono → botón "Panel de edición".
Un pequeño botón circular aparece automáticamente en las páginas que coinciden con cualquier directorio. Por defecto muestra el texto ZIX, pero cada directorio puede tener su propia etiqueta.
Etiqueta del directorio: en la barra del directorio, en el extremo izquierdo (junto al selector de color) hay un campo de texto para la etiqueta del botón. Límites impuestos: máx. 3 caracteres, siempre en MAYÚSCULAS (la conversión a mayúsculas ocurre al instante mientras escribes). El campo acepta letras y cifras — ejemplos: ZIX, QA, DEV, ADM, X. Cuando varios directorios coinciden, se toma la etiqueta del primero que la tenga definida; los demás se ignoran (campo vacío = se recurre a ZIX).
Estado por color (paleta de marca):
Color del directorio: si en el directorio defines el selector de color, el botón flotante en las páginas que coinciden adoptará ese color. Los estados "mixed" y "off" modulan automáticamente la saturación. Cuando varios directorios coinciden, se toma el color del primero que lo tenga definido.
Al entrar en el panel de edición la extensión abre el Panel — la página principal con un resumen de la biblioteca y atajos rápidos. Antes el panel seleccionaba automáticamente el primer directorio de la lista; ahora, en su lugar, ves una vista general.
El Panel es accesible mediante el clic en el logotipo del sidebar y mediante el icono de „casa" en la barra de breadcrumb de cada editor (directorio, grupo, conjunto). La propia cabecera del Panel también tiene un icono de „casa" — al hacer clic en él se actualizan los datos (se recarga la biblioteca desde el storage y se vuelve a renderizar el Panel).
El Panel tiene un diseño con filas fijas de tarjetas:
chrome.storage.local y la fecha de la última copia de seguridad en la nube.Las tarjetas „Últimos ejemplos" y „Del blog" obtienen su contenido de la página del proyecto; cuando el endpoint no está disponible (p. ej. sin conexión), ambas tarjetas se ocultan. La versión de la extensión se comprueba de nuevo cada vez que se entra en el panel.
El panel izquierdo en modo de edición muestra los directorios en jerarquía — puedes desplegar cada directorio para ver sus conjuntos y pasar a editar uno concreto.
| Elemento | Acción |
|---|---|
| Flecha de despliegue | Despliega/contrae la lista de conjuntos o grupos (recordado entre sesiones) |
| Clic sobre el nombre de un directorio (contraído) | Selecciona el directorio, abre el Folder editor y despliega sus grupos/conjuntos |
| Clic sobre un directorio ya seleccionado | Toggle: lo contrae (el siguiente clic lo vuelve a desplegar) — análogamente para el grupo |
| Clic sobre el nombre de un grupo (contraído) | Selecciona el grupo, abre el Group editor y despliega sus conjuntos |
| Clic sobre el nombre de un conjunto | Abre la vista del conjunto individual (Rule editor) |
| Checkbox junto al directorio | Habilita/deshabilita todo el directorio (cascada hacia los grupos y sus conjuntos activos) |
| Checkbox junto al grupo | Habilita/deshabilita el grupo (cascada hacia sus conjuntos activos) |
| Checkbox junto al conjunto | Controla de forma independiente un único conjunto |
| Estado ●/○ junto al directorio/grupo/conjunto | Activo: ● activo, ○ inactivo (forzado a deshabilitado) |
| C J A U junto al conjunto | Etiquetas de contenido: C = tiene CSS, J = tiene JavaScript, A = tiene acciones, U = tiene patrones de URL propios. Aparecen solo cuando el campo correspondiente no está vacío. |
| Barra de color a la izquierda | El color del directorio se dibuja mediante box-shadow inset — no desplaza la posición del nombre de la carpeta (las carpetas con color y sin color quedan alineadas) |
| Asa de drag&drop | Sujétala con el ratón y arrastra para cambiar el orden |
expandedFolders, expandedGroups).
Pasa el cursor sobre un directorio, grupo o conjunto — a la izquierda aparecerá el asa de drag&drop. Sujétala con el ratón y arrastra:
La barra vertical entre el sidebar y el editor oculta el panel izquierdo — útil cuando necesitas más espacio para el editor. El estado se recuerda entre sesiones. Tras mostrar/ocultar, CodeMirror actualiza automáticamente su anchura.
Bajo cada editor (CSS, JS, código de acción) hay una barra horizontal con un asa para arrastrar en vertical. Sujétala con el ratón y arrastra hacia abajo para ampliar el editor. Altura mín. 80px, máx. ilimitada — la página se desplaza de forma natural con el contenido.
Sobre cada editor de código CodeMirror — CSS y JavaScript en la tarjeta del conjunto, así como "Código JS" en el editor de acciones — hay una barra de búsqueda: un campo de texto y un botón con icono de lupa.
n / total.| Atajo | Acción |
|---|---|
Enter | Buscar (nueva consulta) o ir al siguiente resultado (cuando la consulta no ha cambiado) |
Shift+Enter | Resultado anterior |
Ctrl+Alt+→ / Ctrl+Alt+← | Resultado siguiente / anterior — funciona desde el editor y desde el campo de búsqueda |
Ctrl+Alt+F | Desde el editor de código, pasa el foco al campo de búsqueda |
Esc | Borra el campo de búsqueda |
El patrón de URL define en qué páginas se activa el directorio.
| Patrón | Coincide con |
|---|---|
https://justzix.com/admin | Solo esa URL exacta |
https://justzix.com/* | Todas las páginas de justzix.com |
https://*.justzix.com/* | Todos los subdominios y páginas |
*://localhost:*/* | Todas las aplicaciones locales |
https://example.com/admin/* | Solo la sección /admin/ y sus subpáginas |
*example* | Cualquier URL que contenga "example" |
?id=123) y el hash (#section), salvo que los incluyas en el patrón.
Cada conjunto tiene dos flags independientes:
| Flag | Significado |
|---|---|
| Activo ● | Indica si este conjunto está controlado por el interruptor del directorio y del grupo (ambos niveles cascadean hacia las active rules). Habilitar el directorio o el grupo habilita todos los conjuntos activos que contiene. |
| Habilitado ✓ | El estado actual: si el conjunto está ahora inyectado en las páginas. |
Toggle del directorio → cambia enabled de todas las active rules de sus grupos
Toggle del grupo → cambia enabled de todas las active rules de ese grupo
Toggle del conjunto → cambia solo enabled de ese conjunto
Las reglas con Activo: NO (badge ○) se omiten en las cascadas — las controlas solo manualmente, con independencia del estado de la carpeta y del grupo.
Activo: NO • Habilitado: controlado manualmente
El conjunto no reacciona a la habilitación de todo el directorio. Lo controlas solo manualmente. Ideal para modificaciones experimentales que no quieres habilitar de forma masiva.
Activo: SÍ • Habilitado: SÍ
Ajuste estándar. Habilitar/deshabilitar el directorio controla también este conjunto.
Activo: SÍ • Habilitado: NO
El conjunto está "conectado" al directorio, pero deshabilitado por el momento. El próximo clic en el interruptor principal del directorio volverá a activarlo.
| Acción | Efecto |
|---|---|
| Clic izquierdo | Toggle de todos los directorios que coinciden (habilitar/deshabilitar) |
| Clic derecho | Abre un panel con la lista de directorios y conjuntos |
| Arrastre | Cambio de posición (recordado por ventana) |
En el panel desplegable (clic derecho) puedes:
actionBar.enabled (persistente, se propaga al panel de edición)El panel muestra solo los conjuntos activos (●) — los independientes (○) se ocultan por concisión. Cuando la carpeta tiene un único grupo llamado "Predeterminado", la cabecera del grupo se omite — se ven solo los conjuntos.
Hacer clic en el icono de JustZix en la barra de extensiones de Chrome abre el widget del popup — un panel de control compacto para la pestaña actual. De arriba abajo:
actionBar.enabled).En un mismo workspace puedes tener varias barras de acciones — cada una con su propio nombre, orientación, color de fondo, su propio conjunto de botones y una posición independiente por ventana del navegador. La barra puede asignarse a una carpeta, un grupo o un conjunto individual (lo cual decide la visibilidad y la cascada).
En el editor del directorio, del grupo o del conjunto hay un botón "Barras de acciones (N)". El clic abre el modal de gestión de barras. En el modal:
barId).Cada acción de la pestaña "Acciones" de la tarjeta del conjunto tiene un dropdown "Barra de acciones" — eliges la barra de destino de la lista de las visibles para ese conjunto (barras propias del conjunto + barras del grupo + barras de la carpeta).
Durante el arrastre de una barra, la extensión detecta los bordes de barras adyacentes y del botón flotante a una distancia ≤ 12 px. Aparece un indicador visual de adherencia y, al soltar, las barras se unen en un grupo de conexiones. A continuación:
__float como pseudo-barra).Clic derecho sobre el asa de arrastre de la barra → menú contextual:
En el modo de edición de la barra este menú queda silenciado; el clic derecho sobre la etiqueta ofrece entonces la opción "Eliminar etiqueta".
Para habilitar/deshabilitar de forma permanente las barras de acciones (sin F5), la extensión ofrece tres puntos de entrada, todos mapeados al mismo actionBar.enabled en storage — un cambio desde un lugar se propaga al panel de edición y al resto de UIs:
actionBar.enabled.actionBar.enabled = false — la barra no se renderiza en absoluto, el estado se sincroniza entre dispositivos (sync), visible en el panel de edición.barsHidden[barId] = true por ventana del navegador — la barra desaparece hasta F5 / cierre de la ventana. Habilitarla desde el popup/floating panel limpia automáticamente esa ocultación de runtime.El modo de edición de la barra de acciones se activa de tres maneras: con el atajo Ctrl+Alt+S (funciona desde cualquier lugar de la página), con el interruptor del widget del popup de la extensión, y desde el menú contextual de Chrome (clic derecho → "Modo de edición de la barra de acciones"). En la parte superior de la pantalla aparece una barra informativa; volver a usar cualquiera de los interruptores sale del modo.
En el modo de edición, el funcionamiento normal de los elementos queda suspendido (el clic no ejecuta código, los campos no aceptan el foco) — en su lugar, los elementos se pueden distribuir y escalar:
Ctrl+clic = añadir/quitar de la selección; clic en zona vacía o Esc = deseleccionar todo. Shift+arrastre sobre zona vacía = selección por rango (rectángulo).Delete elimina todas las etiquetas seleccionadas a la vez; el clic derecho sobre la etiqueta ofrece la opción "Eliminar etiqueta"; también hay un botón "Eliminar" en el editor de la etiqueta. Los elementos de acción se eliminan en el panel de edición (pertenecen a las reglas).flow): elimina las posiciones y tamaños personalizados de los elementos y todas las etiquetas (con confirmación).Ctrl+Z deshace el último cambio (mover, redimensionar, añadir/editar/eliminar etiqueta, reset). El historial abarca la sesión de edición actual.El modo de edición es "duro": al mover y redimensionar, los elementos se ajustan a una cuadrícula de 8 px, no se puede sacar un elemento fuera de la barra ni colocarlo sobre otro — en caso de colisión, ambos elementos (el que se mueve y el de debajo) reciben un marco rojo y, al soltar, el elemento vuelve a su posición anterior. La barra no se puede reducir de modo que un elemento quede fuera; cuando un nuevo elemento o etiqueta no cabe en la barra, el lienzo de la barra se amplía automáticamente. El clic derecho sobre la barra en modo de edición no muestra el menú "ocultar/desconectar barra".
Modos de disposición de la barra: la barra arranca en modo flow (flexbox clásico — elementos uno tras otro, en vertical u horizontal). El primer movimiento o reescalado de un elemento convierte la barra al modo custom (un lienzo con posicionamiento libre) — sin cambios visuales, ya que la disposición actual se captura como punto de partida.
custom (bar.layoutMode, bar.size, action.layout, action.size) se guardan de forma permanente y se sincronizan entre dispositivos — a diferencia de la posición "flotante" de la barra en la página, que permanece por ventana del navegador.
Cada acción tiene un tipo — se elige con un dropdown al principio de cada acción en la tarjeta del conjunto. Hay disponibles 6 tipos:
| Tipo | UI | Cuándo ejecuta el código |
|---|---|---|
| BUTTON | Botón clicable con una etiqueta de máx. 6 caracteres | clic del usuario |
| SELECT static | Dropdown personalizado con el estilo de la barra — las opciones se configuran en un modal | selección de opción (value = option.value) |
| SELECT js | Un <select> nativo — tu código rellena las opciones y conecta el handler | UNA VEZ al renderizar ($el = <select>) |
| INPUT | Campo de texto con placeholder (una sola línea) | change (Enter o blur) |
| SLIDER | Deslizador <input type="range"> con label + visualización del valor | change (soltar el ratón / Enter), value = número |
| TEXTAREA | Campo multilínea — Enter es un salto de línea legítimo (NO ejecuta el código) | change (blur — salir del campo) |
| TOGGLE3 | Control segmentado de 3 estados (tipo radio) — 3 mini-botones, uno activo | clic sobre un estado inactivo, value = state.value del activo, más stateIdx y stateLabel en el scope |
Las etiquetas de texto estáticas no son un tipo de acción — se añaden directamente en la barra en modo de edición (consulta "Modo de edición de la barra" → etiquetas).
value, $el (elemento DOM), $action ({ id, label, type, el }); para TOGGLE3 además stateIdx (0-2) y stateLabel.El clic en "Opciones (N)" en la tarjeta de una acción de tipo SELECT abre un modal:
<select> nativo).{ name, value }. name = lo que ve el usuario, value = lo que llega a JS como variable value.<option> (variante js)action.id completo con un botón copy + un selector JS de ejemplo.::placeholder no es estilizable inline).min < max.(min+max)/2.change (soltar el ratón / Tab / Enter). value = valor numérico.\n para los saltos de línea).change (blur, NO Enter — Enter en un textarea es un salto de línea legítimo). El usuario sale del campo → el valor se guarda y el código se ejecuta. value = string con saltos de línea.value). Labels por defecto: OFF / MID / ON.colorText).value (state.value, fallback a state.label), stateIdx (0-2), stateLabel, $el (el div contenedor).La selección / valor / posición del deslizador / contenido del textarea / estado activo del toggle3 se recuerdan automáticamente por acción. Tras F5 el valor vuelve; tras cerrar la pestaña y volver a abrirla (en una página que coincida con la regla) también. Singleton por action.id — un valor independiente de la URL concreta.
Formato del valor en la memoria según el tipo:
Storage:
sessionStorage — síncrono, F5-safe, por pestaña.chrome.storage.local.actionMemory[id] — cross-tab, duradero.Sin sincronización cross-device: la memoria permanece en local. Dos ordenadores pueden tener valores distintos (p. ej. un filtro distinto por usuario).
sessionStorage es legible por los scripts de la página (mismo origin). Para datos sensibles no uses INPUT — en su lugar, escribe el valor directamente en el campo "Código JS" del conjunto.
Cada acción tiene un action.id inmutable (formato a_<base36>_<random>). En la tarjeta del conjunto, junto a cada acción hay un badge con el número de fila — el clic copia el ID completo al portapapeles, el tooltip muestra el ID completo.
En el user-JS, refiérete a ella mediante data-jz-action-id:
const el = document.querySelector('[data-jz-action-id="a_mp1deeq3_uimd8l"]');
el.value = 'nuevo valor';
el.dispatchEvent(new Event('change'));
O mediante los helpers window.JZ — consulta Invocación programática de acciones desde JS.
Clic derecho en cualquier página → JustZix:
Ctrl+Alt+S y al interruptor del popup.actionBar.enabled.Los submenús de ventanas se reconstruyen en: tabs.onActivated, tabs.onUpdated (cambio de URL), y storage.onChanged para folders/groups/rules/actionBars/cssPanes/jsPanes/jsConsoles/outputConsoles/floatingHidden. El submenú TEMP es estático (siempre 4 elementos).
La extensión ofrece cuatro tipos de ventanas flotantes inyectadas en las páginas, junto a las barras de acciones. Cada ventana está asignada a una carpeta, grupo o conjunto (hereda la visibilidad en cascada, igual que las barras de acciones) y aparece en las páginas que coinciden por URL.
Gestión: en el editor de la carpeta / grupo / conjunto encontrarás un botón "Ventanas ▾ (N)". El clic despliega un menú con los 4 tipos — eliges el tipo y se abre un modal con la lista de ventanas de ese nivel (más las ventanas heredadas de niveles superiores). Las añades, nombras, coloreas, eliminas.
| Tipo | Color | Para qué |
|---|---|---|
| CSS pane | verde | Un textarea de CSS inyectado en vivo como <style> |
| JS pane | ámbar | Un textarea de JS ejecutado al cambiar el código |
| JS Console | morado | REPL — escribes código, Ctrl+Enter lo ejecuta, el output aparece debajo |
| Output Console | esmeralda | Vista de solo lectura de los logs de la página (console.* + errores) |
Una ventana flotante con un campo de texto para CSS. Cada cambio (tras una breve pausa) actualiza el <style> inyectado — ves el efecto en vivo. El contenido se recuerda por pestaña del navegador (sobrevive a F5, desaparece al cerrar la pestaña). Ideal para probar CSS rápidamente sin guardarlo en una regla.
Un campo de texto para JavaScript ejecutado en el contexto de la página. El código se ejecuta tras un cambio (con retardo) o manualmente con el botón ▶ Run / el atajo Ctrl+Enter. Los errores de ejecución aparecen en una barra roja bajo el código. Cuando el código se ha modificado desde la última ejecución, el botón Run se ilumina en amarillo (estado "dirty").
Una consola completa dentro de la página. Escribes código en el campo inferior, Ctrl+Enter (o ▶) lo ejecuta, el resultado se añade al área de logs superior. Funciones:
console.log/warn/error/info durante la ejecución se muestran en el log (coloreadas según el tipo).El input, el output y el historial se recuerdan por pestaña. La consola ejecuta el código en el MAIN world de la página — tienes acceso a todas las variables y funciones de la página.
Una vista de solo lectura de los logs — captura automáticamente todo lo que ocurre en la página: console.log/warn/error/info/debug, excepciones no capturadas, Promise rejections no manejadas, el tráfico de red y los push a dataLayer, así como tu propio logger window.JUSTZIX.*. A diferencia de la JS Console (donde tú mismo escribes el código), aquí los logs fluyen solos.
La ventana se divide en 6 pestañas, cada una con un contador de entradas (badge):
| Pestaña | Contenido |
|---|---|
| All | Todas las entradas de todas las fuentes, en orden cronológico |
| JZconsole | Solo tu logger window.JUSTZIX.* |
| Console | Solo los console.log/info/warn/error/debug estándar de la página |
| Network | Peticiones de red de la página (mediante chrome.webRequest) |
| Errors | Excepciones no capturadas y Promise rejections — con detalles desplegables |
| DataLayer | Push a window.dataLayer (GTM) + vista en vivo del objeto |
Entre las pestañas y el campo de búsqueda hay una barra de filtros que cambia según la pestaña seleccionada:
log, info, warn, error, debug. Desmarca un nivel → las líneas desaparecen de la vista.Bajo la barra de filtros hay un campo de búsqueda siempre visible. Filtra en vivo las entradas de la pestaña activa (coincidencia de fragmento, sin distinguir mayúsculas). Esc limpia el campo.
Las entradas console.* aparecen por defecto contraídas — muestran una vista previa abreviada (p. ej. [PickupMap][2026-05-16T15:25Z] AUTO_SELECTION_SKIPPED: {reason: 'Lower priority source', …}). El clic despliega los argumentos completos (objetos/arrays como un árbol JSON desplegable), análogamente a la consola de DevTools.
Network captura las peticiones mediante chrome.webRequest (permiso webRequest en el manifest). Cada entrada muestra, entre otras cosas, el método, la URL, el estado, el tipo de recurso, el tamaño, la duración, la dirección remota (Remote address) y el iniciador (Initiator). El búfer de peticiones se mantiene en segundo plano, por lo que las entradas anteriores a la apertura de la ventana también aparecen.
La ventana DataLayer se divide en dos columnas:
dataLayer.push(...) en orden de eventos.window.dataLayer como un árbol JSON desplegable e indexado (0:, 1:, …) — profundizas en los datos anidados, análogamente al inspector de objetos de DevTools. La instantánea se actualiza tras cada push. En la cabecera de la columna derecha hay botones desplegar todo / contraer todo — funcionan recursivamente sobre todo el árbol.Los clics en la propia interfaz de JustZix (desplegar nodos del árbol, botones de la ventana) no llegan a esta pestaña. Si la página recopilara eventos click (p. ej. GTM auto-event), un clic en la ventana generaría un push a dataLayer y restablecería el despliegue del árbol — la extensión reconoce esos push y no los reporta (el window.dataLayer real de la página permanece intacto).
La Output Console expone una API global para registrar desde tu código (JS pane, acciones, código de la página):
JUSTZIX.log('log normal');
JUSTZIX.warn('advertencia');
JUSTZIX.error(new Error('error')); // mostrará el stack trace
JUSTZIX.info({ obj: 1, arr: [2,3] });
JUSTZIX.debug('detalles'); // oculto por defecto (filtro)
Alias disponibles:
window.JUSTZIX — el principal, siempre funcionawindow.__JUSTZIX__ — un alias siempre disponiblewindow.JZ — un alias solo si la página no tiene su propio window.JZ (algunas páginas, p. ej. Google Ads, ocupan ese nombre)Tras aparecer la Output Console verás en el log una línea de bienvenida que indica qué alias está disponible en esa página.
console.log/warn/error/info/debug(...) de la página — también pasan a la consola normal de DevTools (no la bloqueamos)window.JUSTZIX.*(...) — tu canal dedicado (no va a DevTools)throw new Error(...)) — mostradas en rojo con el lugar del errorPromise.reject(...) sin .catchLos errores de las peticiones fetch/XHR no llegan a la pestaña Errors (no son excepciones JS) — los encontrarás en la pestaña Network por el estado 4xx/5xx. No capturamos las violaciones de CSP ni las advertencias internas de Chrome.
Ctrl+Shift+H abre una ventana desplazable de ayuda rápida — una guía para usar JustZix en la página: atajos globales, atajos dentro de las ventanas, la Consola Output, manejo de las ventanas con el ratón, el modo edición de barra y el registro en la Consola Output. Funciona en cualquier página. Arrastras la ventana por la cabecera; Esc / clic fuera / × / volver a pulsar Ctrl+Shift+H la cierra.
Colores: en el modal de gestión (panel de edición) cada ventana tiene un selector de color — el punto de la cabecera, el fondo y el texto de la cabecera, el fondo y el texto del body, el color de los botones de acción.
Fuente y tamaño: clic derecho sobre la barra de cabecera de la ventana → un menú con selección de fuente (Consolas, Menlo, Monaco, Courier New y otras monospace) y de tamaño (10–24 px).
Cada ventana se arrastra por la barra de cabecera. Al acercar un borde a otra ventana / barra de acciones / botón flotante (≤ 12 px) aparece una atracción magnética — las ventanas se pegan formando un grupo. Arrastrar un grupo pegado mueve todos los elementos juntos. Las posiciones se recuerdan por ventana del navegador.
Cada ventana tiene 8 asas de redimensionado: 4 en las esquinas (cambio de anchura y altura a la vez) y 4 en los bordes (cambio de un solo eje). El asa arrastrada mantiene el borde opuesto en su sitio. Rango: anchura 180–1200 px, altura 120–900 px. El nuevo tamaño (pane.size) se guarda — para las ventanas permanentes se sincroniza entre dispositivos, para las ventanas TEMP por pestaña.
El desplazamiento con la rueda del ratón dentro de una ventana desplaza únicamente el contenido de esa ventana — la página de debajo no se desplaza. Esto también se aplica cuando el área de la ventana llega al final del desplazamiento o cuando el cursor está sobre una parte no desplazable (la cabecera, la barra de filtro).
Cada ventana (tanto temporal TEMP como persistente) tiene un botón × de cerrar en la esquina derecha de la cabecera. Las TEMP se ocultan (reábrelas desde el menú contextual de la página o con un atajo), las persistentes — se desactivan (reactívalas con la casilla en el popup). Doble clic en la barra de la cabecera:
Cuando el borde de una ventana se acerca a otra ventana de JustZix (umbral de 12 px), aparece un borde rojo en el lado del pegado (en ambas ventanas). Soltar el cursor en esta posición ejecuta el snap — las ventanas se mueven después como grupo. Todas las ventanas de la extensión participan en este mecanismo: barras de acciones, FAB, paneles persistentes (CSS/JS/Console/Output), TEMP y el AI Helper.
Puedes crear una ventana temporal en cualquier página — incluso una para la que no tengas ninguna carpeta. Los paneles TEMP son una herramienta rápida ad-hoc: pruebas CSS/JS en una página ajena sin configurar reglas.
Características de los paneles TEMP:
<style> en vivo se actualiza al instante.Creación / cierre (toggle):
AI Helper es un asistente de IA integrado en la extensión que ayuda a preparar e implementar una solución CSS/JS para una tarea concreta en la página actual. El modelo puede examinar la página, probar código en vivo en ventanas TEMP y — tras tu aceptación — crear un directorio, grupo y conjunto listos para usar.
En el menú Ajustes del sidebar, el elemento "AI Helper" abre un modal de configuración:
chrome.storage.local). La clave llega a otros dispositivos solo cuando marcas su checkbox "sincronizar" — entonces se sincroniza mediante la nube de JustZix (el mismo canal por el que la extensión sincroniza carpetas, grupos y conjuntos). Las claves sin marcar nunca salen del dispositivo. Las llamadas a la API van a través del service worker de la extensión, de modo que la clave no llega al contexto de la página.
La ventana de AI Helper es una ventana flotante (por pestaña, como las ventanas TEMP — arrastrable, escalable con 8 asas, con cruz de cierre, una sola instancia). La abres / cierras:
En la ventana: selección del proveedor (cuando tienes más de una clave) y del modelo (lista obtenida en vivo), el historial de la conversación, un botón para limpiar la conversación y un campo de texto (se envía con el botón o con Ctrl+Enter). El modelo recibe automáticamente el contexto de la página actual — URL, título y un fragmento del HTML.
AI Helper conduce la conversación según un workflow establecido:
query_page (selectores, estructura del DOM) antes de escribir el código.read_temp_pane y read_console comprueba que el código probado no reporte errores antes de mostrarte el resultado.El modelo usa las herramientas mediante un protocolo de texto simple (un bloque @@JZ_TOOL@@ … @@END@@) que funciona de forma idéntica para OpenAI, Anthropic y Gemini. Las llamadas a las herramientas y sus resultados aparecen en la ventana como "chips" aparte. Herramientas disponibles:
| Herramienta | Acción |
|---|---|
query_page | Devuelve el número de coincidencias del selector y el HTML de hasta 5 elementos |
list_structure | Devuelve los directorios / grupos / conjuntos existentes junto con sus id |
open_temp_pane | Abre una ventana temporal TEMP (CSS o JS) |
set_temp_pane_code | Inserta código en una ventana TEMP — sirve para pruebas en vivo |
read_temp_pane | Verifica la ventana TEMP — para JS ejecuta el código y devuelve error o éxito |
read_console | Abre una ventana TEMP Output Console y devuelve las entradas de console capturadas de la página |
create_folder | Crea una carpeta + un grupo por defecto (requiere confirmación) |
create_group | Crea un grupo en una carpeta (requiere confirmación) |
create_rule | Crea un conjunto con código CSS/JS (requiere confirmación) |
create_bar | Crea una barra de acciones asociada a una carpeta/grupo/conjunto (requiere confirmación) |
create_action | Crea una acción (button/select/input/slider/textarea/toggle3) en una barra (requiere confirmación) |
request_user_input | Muestra al usuario un formulario en línea en la ventana de chat (campos de texto / número / color / select / casilla) y espera la respuesta |
list_bars / list_actions / list_panes / list_all | Devuelven listas de barras de acciones / acciones / ventanas (CSS/JS/Console/Output) existentes — opcionalmente filtradas por padre |
read_folder / read_group / read_rule / read_bar / read_action | Devuelven los datos completos de una entidad específica (antes de un cambio planeado) |
update_folder / update_group / update_rule / update_bar / update_action | Modifican una entidad existente — requiere confirmación (con un diff de campos) |
create_css_pane / create_js_pane / create_js_console / create_output_console | Crean una ventana persistente en la página (requiere confirmación) |
read_*_pane / read_*_console + update_*_pane / update_*_console | Lectura y modificación de los metadatos de las ventanas persistentes (nombre, color, posición, tamaño, estilo) |
read_pane_code / update_pane_code | Lectura e inserción del código CSS/JS en una ventana persistente (por pestaña del navegador) — requiere confirmación |
screenshot_page | Captura de la vista actual de la página como imagen — la interfaz de JustZix se oculta automáticamente; para modelos compatibles con visión |
read_temp_pane + read_console), pedirte datos mediante un formulario en línea (request_user_input) y hacer capturas de la página (screenshot_page) como imágenes adjuntas a la siguiente solicitud.
Un clic derecho sobre la barra del encabezado de la ventana de AI Helper abre un menú con las opciones «Traer al frente» / «Enviar al fondo» (cambiar el orden de las ventanas JustZix cuando se superponen), «Desconectar de: X» (cuando AI Helper está pegado a otra ventana) y «Apariencia…». El panel «Apariencia…» permite estilizar por separado cuatro roles en la conversación: tus mensajes, respuestas de la IA, resultados de herramientas, formularios en línea — cada uno con su propia fuente, tamaño, color de texto y de fondo. Los valores se guardan por dispositivo.
La ventana de AI Helper participa del mismo mecanismo de pegado que las barras de acciones, las ventanas persistentes (CSS / JS / Console / Output) y las ventanas TEMP. Arrastrar un borde cerca de otra ventana de JustZix (umbral de 12 px) → atracción magnética, un borde rojo indica el lado del pegado en ambas ventanas. Las ventanas pegadas se mueven como grupo.
Cuando las ventanas se solapan, las opciones «Traer al frente» / «Enviar al fondo» en el menú contextual de cada ventana (clic derecho en el encabezado) hacen un salto único — la ventana pasa por encima / por debajo de todos los vecinos que se solapan, sin necesidad de hacer clic varias veces.
La herramienta screenshot_page captura la vista actual de la página y la envía al modelo como imagen. Toda la interfaz de JustZix se oculta automáticamente antes de la captura (FAB, barras de acciones, AI Helper, paneles persistentes, TEMP). Un búfer de las 3 capturas más recientes, adjuntadas una sola vez a la siguiente solicitud (tras enviar — eliminadas del búfer, para ahorrar tokens). Requiere un modelo compatible con visión (p. ej. gpt-4o, claude-3+/4, gemini-1.5+/2). Debajo del chip de resultado en el chat aparece una miniatura — un clic abre la vista a pantalla completa.
| Atajo | Acción |
|---|---|
Ctrl+Alt+G | Crear / cerrar TEMP CSS pane |
Ctrl+Alt+H | Crear / cerrar TEMP JS pane |
Ctrl+Alt+J | Crear / cerrar TEMP JS Console |
Ctrl+Alt+K | Crear / cerrar TEMP Output Console |
Ctrl+Alt+I | Abrir el panel de edición (ventana separada), primer conjunto activo en esta página, pestaña CSS |
Ctrl+Alt+O | Como arriba, pestaña JS |
Ctrl+Alt+P | Como arriba, pestaña Acciones |
Ctrl+Alt+\ | Abrir / cerrar la ventana de AI Helper |
Ctrl+Alt+S | Modo de edición de la barra de acciones — habilitar / deshabilitar |
Ctrl+Z | Deshacer el último cambio (solo en modo de edición de la barra) |
Delete | Eliminar las etiquetas seleccionadas (solo en modo de edición de la barra) |
Esc | Deseleccionar todos los elementos (solo en modo de edición de la barra) |
Ctrl+Shift+L | Limpiar la pestaña activa de cada Output Console |
Ctrl+Shift+H | Ayuda rápida — atajos y ventanas en la página (en todas partes) |
| Atajo | Acción | Ventana |
|---|---|---|
Ctrl+Enter | Ejecutar el código / enviar el mensaje | JS pane, JS Console, AI Helper |
↑ / ↓ | Historial de comandos | JS Console (input) |
Ctrl+L | Limpiar el output | JS Console |
Esc | Limpiar el campo de búsqueda | Output Console |
| Atajo | Acción |
|---|---|
Ctrl+Alt+F | Foco en el campo de búsqueda sobre el editor |
Ctrl+Alt+→ / Ctrl+Alt+← | Resultado de búsqueda siguiente / anterior |
Enter / Shift+Enter | Buscar / resultado siguiente / anterior (en el campo de búsqueda) |
Ctrl+Alt+I / O / P | Cambiar la pestaña del conjunto activo a CSS / JS / Acciones (cuando la tarjeta del conjunto está renderizada) |
Ctrl+Alt+G/H/J/K son teclas contiguas (disposición Vim), todas libres en todos los navegadores y sistemas. Ctrl+Alt+L se omitió a propósito — en Linux bloquea la pantalla. Ctrl+Alt+S (modo de edición) y Ctrl+Alt+\ (AI Helper) están en la misma familia de modificadores. Los atajos de la Output Console (Ctrl+Shift+...) no colisionan, porque se diferencian por el modificador.
La extensión ofrece cinco formatos de exportación (completo, parcial, directorio, grupo, conjunto) con detección automática del tipo de archivo al importar, para evitar sobrescrituras accidentales.
En el menú Ajustes del sidebar: Exportar ajustes. El modal abre dos modos:
Los archivos de exportación parcial tienen el nombre justzix-partial-FECHA.json (frente a justzix-backup-FECHA.json para el completo), y dentro un flag partial: true y un campo groups[].
En la barra del directorio: Exportar — abre un modal con un árbol de grupos y conjuntos (análogo al de la exportación parcial, pero limitado a ese directorio). Se exportan solo los conjuntos marcados y los grupos a los que pertenecen — los grupos vacíos no llegan al archivo.
Formato justzix-folder — el archivo contiene un campo groups[] con la jerarquía de grupos y conjuntos del directorio.
En la barra del grupo: Exportar — un modal con la lista de conjuntos del grupo (checkboxes). Archivo: justzix-grupo-<nombre>-<fecha>.json, formato justzix-group.
En la vista del conjunto: Exportar conjunto — descarga el archivo inmediatamente (sin modal). Formato justzix-rule, nombre: justzix-conjunto-<nombre>-<fecha>.json.
justzix-full — backup completo de todojustzix-full con partial: true — elementos seleccionados de la exportación principaljustzix-folder — un directorio individual con un árbol de selecciónjustzix-group — un grupo + los conjuntos marcadosjustzix-rule — un conjunto individualTras cargar un archivo / pegar el JSON, la extensión reconoce automáticamente el tipo y muestra un panel de detección coloreado:
| Color | Significado | Acción |
|---|---|---|
| Teal (turquesa) | Backup completo válido | Muestra el número de directorios/conjuntos, la fecha de exportación, una advertencia de sobrescritura |
| Morado | Backup parcial (partial: true) | Elección de modo: Fusionar con los actuales o Reemplazar todo |
| Naranja | Tipo de archivo incorrecto en este modal | Un mensaje que orienta al modal correcto, el botón Importar bloqueado |
| Rojo | Error de parseo del JSON / formato no válido | El botón Importar bloqueado |
1 / sobrescribir — sobrescribe los directorios existentes (eliminará sus grupos y conjuntos)2 / copia (predeterminado) — importa como copias con nuevos ID, "(import)" en el nombre de la carpeta, sin pérdida de datos existentesEn la barra del directorio: Importar. Comprueba conflictos por ID y por nombre:
En la barra del grupo: Importar — acepta 3 formatos:
justzix-group — inserta todos los conjuntos del grupo del archivojustzix-folder — inserta todos los conjuntos de todos los grupos de la carpetajustzix-rule — inserta un conjuntoTodos los conjuntos del archivo llegan al grupo actual con nuevos ID (la operación es siempre del tipo "añadir copia" — sin conflictos).
En la vista del conjunto: Importar conjunto — acepta solo justzix-rule. Un prompt con 3 opciones:
1 / reemplazar — reemplaza el contenido del conjunto actual (id y groupId conservados)2 / copia (predeterminado) — añade como un conjunto nuevo junto al actual, en el mismo grupo, con el añadido "(import)"Ajustes → Sincronización en la nube abre el modal de la cuenta de sincronización. La extensión mantiene tu biblioteca (directorios, grupos, conjuntos, acciones, barras de acciones, ventanas en el frontend) en la nube de justzix.com y la conserva coherente entre dispositivos. La sincronización funciona solo cuando has iniciado sesión — sin una cuenta la extensión funciona únicamente en local.
Al iniciar sesión, la extensión compara los datos locales con los datos de la nube:
| Elección | Qué hace |
|---|---|
| Usar los datos de la nube | Borra la biblioteca local y reconstruye el estado de la cuenta a partir del servidor |
| Enviar mis datos locales | Los datos locales pasan a ser los canónicos — elimina lo que había en la nube |
| Fusionar | Combina ambos conjuntos — añade las entidades que faltan, conservando las existentes |
También puedes Cancelar — la extensión cierra entonces la sesión y no cambia nada.
Tras la primera conciliación, la sincronización se ejecuta en segundo plano: la extensión envía los cambios y descarga las nuevas entidades aproximadamente una vez por minuto. Un cambio realizado en un dispositivo aparece en los demás al cabo de poco tiempo. El punto de estado junto al elemento "Sincronización en la nube" indica si la cuenta está conectada.
La pestaña Estado del modal de sincronización muestra el estado de la cuenta y ofrece botones de acción:
Contadores de las entidades que se encuentran en la cuenta: directorios, grupos, conjuntos, acciones, barras de acciones, ventanas en el frontend. Solo se cuentan las entidades alcanzables en el árbol (un grupo debe tener un directorio existente, un conjunto — un grupo, una barra/ventana — un padre existente) — de forma coherente con los contadores del Panel. Se actualizan al abrir el panel y tras una sincronización manual.
Un registro local del dispositivo de las últimas sincronizaciones. En la página se ven las últimas 10 entradas; el botón «Ver historial completo» abre una ventana con la lista completa (hasta 100 entradas). Cada entrada contiene:
El registro es local — no se sincroniza entre dispositivos. Se crea una entrada tras cada tick de sincronización que cambió algo realmente; el «Sincronizar ahora» manual siempre deja una entrada, incluso sin ningún cambio.
Las estadísticas de uso (aplicaciones de CSS, ejecuciones de JS, visualizaciones de ventanas) se sincronizan como entidades separadas por dispositivo — la tarjeta del Panel las suma de todos los dispositivos emparejados. El tema y el idioma se sincronizan como un ajuste común de la cuenta y se aplican en la siguiente apertura del panel en el otro dispositivo.
Una alternativa a enviar un archivo JSON por mensajería. Generas un enlace público con un tiempo de vida (1h / 6h / 12h / 24h / 48h) y se lo pasas al destinatario. El backend de justzix.com guarda el payload en la nube hasta su caducidad, después se elimina.
Requiere una cuenta de sincronización (Sync) con la sesión iniciada. El token en sí es un secreto público — cualquiera con el enlace lo descargará, así que no lo envíes por canales públicos si el contenido es sensible.
JZS-XXXX-XXXX-XXXX-XXXX (16 caracteres Crockford base32, ~80 bits de entropía). También se acepta la URL completa https://www.justzix.com/s/JZS-... — la extensión la parsea y normaliza (las letras confusas I/L→1, O→0, U→V).
Superar el límite = un error con un mensaje. Revoca los enlaces que no uses en el panel Mis shares.
El botón "Compartir URL" en cuatro puntos de entrada, junto a "Descargar archivo":
justzix-full)justzix-folder)justzix-group)justzix-rule)El clic abre el modal de generación del enlace: subject + summary de lo que compartes, un radio con el TTL (24h por defecto), "Generar enlace". Tras el éxito, el modal cambia a la vista del resultado con dos valores copiables:
https://www.justzix.com/s/JZS-... — para enviar a alguien sin la extensión (mostrará una página de landing)JZS-XXXX-XXXX-XXXX-XXXX — para pegar en la extensión del destinatario, en "Importar desde URL"Cada uno tiene su botón "Copiar". También se muestra la hora de caducidad en la zona horaria local.
Ajustes → Mis shares (un modal aparte, no forma parte de la sincronización — son dos funcionalidades distintas). Muestra la lista de enlaces activos: un contador en la cabecera X/20 activos · Y MB / 50 MB, y para cada share una tarjeta con:
X directorios · Y grupos · Z conjuntos · N líneas de JS · A KBRevocar no retira el contenido ya descargado. Si alguien llegó a descargar el payload, lo tiene en local. El share es un "best-effort time-limit", no un DRM.
Ajustes → Importar desde URL (entre "Importar ajustes" y "Sincronización en la nube", el icono de cadena). El modal tiene dos pasos:
Paso 1 — input. Pegas el enlace o solo el token. Validación del lado del cliente: se extrae el token de la URL, se normaliza en Crockford-base32, se comprueban los 16 caracteres + el formato. Formato incorrecto → un mensaje con una pista sobre el formato correcto.
Paso 2 — preview. La extensión muestra el resumen del share:
Si el share contiene JavaScript (jsLines > 0) — aparece un banner rojo de advertencia con un enlace "Mostrar el código JavaScript". Abre un overlay con el código JS completo de cada regla y acción — revísalo antes de importar, porque el código se ejecutará en las páginas que coincidan.
Paso 3 — importación. Clic en "Importar" → el backend devuelve el payload completo → la extensión crea las nuevas entidades con ID siempre nuevos (nunca sobrescribe los existentes por ID):
| Tipo | Qué ocurre |
|---|---|
justzix-rule | Crea un nuevo directorio + grupo "Predeterminado" + el conjunto importado |
justzix-group | Crea un nuevo directorio + el grupo importado + los conjuntos |
justzix-folder | Añade como un nuevo directorio de nivel superior |
justzix-full | Merge: añade todos los folders/groups/rules con ID nuevos |
Nombre del nuevo contenedor: <nombre-del-emisor o "Import"> <fecha> — luego puedes renombrarlo / trasladarlo libremente.
| Error | Mensaje |
|---|---|
| Token no válido | "El token no es válido. Comprueba si has copiado el enlace completo." |
404 not_found | "Este enlace ha caducado o ha sido revocado por el emisor. Pide uno nuevo." |
429 rate_limited | "Demasiados intentos. Espera un momento e inténtalo de nuevo." |
| 5xx / network | "Problema con el servidor. Inténtalo de nuevo." |
El backend no distingue un 404 "nunca existió" de un 404 "caducado / revocado" — a propósito, para no revelar si el token existió alguna vez.
Puedes invocar cualquier acción (de la pestaña "Acciones" de la tarjeta del conjunto) de forma programática desde el JS del conjunto o desde el código de otra acción. El namespace global window.JZ se instala automáticamente en el MAIN world antes de cada ejecución de user-JS.
| Llamada | Qué hace |
|---|---|
JZ.click(labelOrId) | Hace clic de forma programática. Semántica según el tipo de acción: BUTTON → el.click(). SELECT static (botón con dropdown) → el.click() (abre el popup; el usuario elegirá la opción manualmente). SELECT js (<select> nativo) → establece value en la primera opción non-disabled y hace dispatch de change. INPUT / TEXTAREA / SLIDER → el.click() — atención: no cambia el valor ni dispara el handler change. Para establecer el valor: const el = JZ.action('LBL'); el.value = 'X'; el.dispatchEvent(new Event('change')). TOGGLE3 — el.click() incide en el contenedor; para activar un estado concreto usa el.querySelector('.jz-toggle3-state[data-jz-state-idx="1"]').click(). Devuelve true/false. |
JZ.value(labelOrId) | Getter unificado del valor actual. INPUT / TEXTAREA → el.value nativo. SLIDER → wrap.dataset.jzValue (wrap es un DIV, el renderer establece el data attr desde el inicial + en input/change). SELECT(js) → el.value nativo. SELECT(static) → el.dataset.jzValue (el renderer lo establece en cada selección). TOGGLE3 → el.dataset.jzValue (state.value del activo; fallback a state.label). BUTTON → null. Elemento no encontrado → null. |
JZ.setValue(labelOrId, value) | Setter programático. INPUT/TEXTAREA → el.value = String(v) + dispatch de input+change. SLIDER → establece el <input.jz-action-slider> nativo + dispatch. SELECT(js) → el.value = String(v) + dispatch de change. SELECT(static) + TOGGLE3 → envía un CustomEvent 'jz-set-value', el listener de content.js hace el flujo completo (memoria + UI + ejecuta el código). Búsqueda en TOGGLE3: por state.value → fallback a state.label → fallback al idx numérico 0-2. BUTTON → false. Devuelve true/false. |
JZ.action(labelOrId) | Devuelve el elemento de la acción (button / select / input / textarea / slider / contenedor toggle3) o null. Búsqueda: primero por data-jz-action-id, luego case-insensitive por data-jz-key (el label en MAYÚSCULAS). Funciona para los 6 tipos de acción. |
JZ.actionById(id) | Búsqueda exclusivamente por el action.id estable (p. ej. 'a_mp1deeq3_uimd8l'). Recomendado para acciones sin label o cuando quieres certeza. |
JZ.actions() | Un array de todos los elementos de acción visibles (button + select + input + textarea + slider + toggle3) de la página actual. |
JZ.labels() | Un array de las etiquetas originales (con el case conservado tal como lo escribiste). |
// === Lectura ===
const filter = JZ.value('FILT'); // INPUT/TEXTAREA — string
const opacity = JZ.value('OPAC'); // SLIDER — string numérico ("75")
const mode = JZ.value('MODE'); // SELECT static — string (option.value)
const theme = JZ.value('THM'); // TOGGLE3 — state.value del estado activo
// === Establecimiento ===
JZ.setValue('FILT', 'nuevo valor'); // INPUT/TEXTAREA — string + dispatch input+change
JZ.setValue('OPAC', 75); // SLIDER — clamp a min/max, dispatch input+change
JZ.setValue('SRT', 'prod'); // SELECT(js) — select nativo + dispatch change
JZ.setValue('MODE', 'staging'); // SELECT static — content.js hace el flujo (memoria + UI + código)
JZ.setValue('THM', 'dark'); // TOGGLE3 — búsqueda por state.value (fallback a label, luego idx)
JZ.setValue('THM', 2); // TOGGLE3 — equivalente; el idx numérico también funciona
| Llamada | Qué hace |
|---|---|
JZ.bars() | Todos los contenedores .jz-actions-bar (ActionBars) visibles en la página. |
JZ.barById(id) | El elemento de la barra por data-jz-bar-id. |
JZ.floatingBtn() | El botón flotante principal #justzix-floating-btn o null (cuando está oculto). |
JZ.click / JZ.action es case-insensitive por el label, pero exacta por el action.id estable. Para acciones sin label (típicamente INPUT) usa JZ.actionById('a_...').
En el campo "Código JS" de la acción tienes disponibles automáticamente unas variables — inyectadas como const por el background service worker antes de la ejecución:
| Variable | Qué contiene | Cuándo está disponible |
|---|---|---|
$el | El elemento DOM de esa acción (input / select / button / textarea / contenedor toggle3) | siempre que exista action.id |
$action | { id, label, type, el } | siempre |
value | El valor actual según el tipo: SELECT static → option.value; INPUT/TEXTAREA → el contenido del campo; SLIDER → un número; TOGGLE3 → state.value del estado activo (fallback a state.label cuando value está vacío). | SELECT static, INPUT, TEXTAREA, SLIDER, TOGGLE3. SELECT js: el código se ejecuta UNA VEZ al renderizar — value está vacío. |
stateIdx | Integer 0-2 — el índice del estado activo (desde qué estado empezó el clic). | solo TOGGLE3 |
stateLabel | String — el label del estado activo (máx. 5 caracteres). | solo TOGGLE3 |
En el modal de configuración de una acción de tipo SELECT e INPUT, el panel "ID estable de la acción" muestra el action.id completo con un botón copy y un selector JS de ejemplo (document.querySelector('[data-jz-action-id="..."]')). Bajo la lista de BUTTON se ven chips JZ.click('LBL') — el clic en el chip copia el snippet al portapapeles.
visible: true, la barra es visible en el árbol + la URL de la página coincide con las reglas).JZ.click() devolverá false, JZ.action() devolverá null.JZ.click().// Código de la acción "AUTO"
JZ.click('LOAD'); // clic en la acción LOAD (p. ej. carga datos)
setTimeout(() => JZ.click('PROC'), 500); // 500ms después PROC (procesa)
setTimeout(() => JZ.click('SAVE'), 1500); // 1500ms después SAVE (guarda)
Tras aparecer un elemento dinámico, haz clic en la acción que lo elimina:
// Código JS del conjunto — un observer sobre un modal que aparece dinámicamente
const observer = new MutationObserver(() => {
if (document.querySelector('.cookie-banner')) {
JZ.click('CCK'); // haz clic en la acción que elimina el banner
observer.disconnect();
}
});
observer.observe(document.body, { childList: true, subtree: true });
// JZ.click sobre un INPUT no cambia el valor — usa el patrón con dispatch de 'change':
const el = JZ.action('SRCH'); // o JZ.actionById('a_mp1deeq3_uimd8l')
if (el) {
el.value = 'nuevo filtro';
el.dispatchEvent(new Event('change'));
}
Si prefieres trabajar con el DOM directamente (p. ej. cambias un estilo, no invocas):
// Búsqueda por el ID estable (recomendado — resistente al cambio del label):
const el = document.querySelector('[data-jz-action-id="a_mp1deeq3_uimd8l"]');
// Búsqueda por el label (case-insensitive — MAYÚSCULAS en data-jz-key):
const btn = document.querySelector('[data-jz-key="MYBT"]');
btn.style.opacity = '0.5'; // atenúalo
btn.dataset.busy = 'true'; // atributo propio
Dónde viven los elementos de acción en el DOM:
| Tipo de acción | Contenedor | Selector del elemento |
|---|---|---|
| BUTTON | .jz-actions-bar[data-jz-bar-id="..."] | .jz-action-btn[data-jz-action-id="..."] |
| SELECT (static) | .jz-actions-bar | .jz-action-select[data-jz-action-variant="static"] (button con popup; data-jz-value = el valor seleccionado actualmente) |
| SELECT (js) | .jz-actions-bar | .jz-action-select.jz-variant-js (<select> nativo) |
| INPUT | .jz-actions-bar | .jz-action-input[data-jz-action-id="..."] |
| SLIDER | .jz-actions-bar | .jz-action-slider-wrap[data-jz-action-id="..."] (wrap); el slider en sí: .jz-action-slider (<input type="range"> nativo) |
| TEXTAREA | .jz-actions-bar | .jz-action-textarea[data-jz-action-id="..."] |
| TOGGLE3 | .jz-actions-bar | .jz-action-toggle3[data-jz-action-id="..."] (contenedor; data-jz-value = state.value del activo); los botones de estado: .jz-toggle3-state[data-jz-state-idx="0|1|2"], el activo tiene la clase .active |
Todos los elementos tienen el atributo data-jz-action-id (un identificador estable único). El selector .jz-actions-bar es seguro — no colisiona con el DOM de la página.
data-jz-key) funciona para todos los tipos de acción. Cada elemento de acción tiene tanto data-jz-label (el case original) como data-jz-key (MAYÚSCULAS). Por seguridad (p. ej. cuando el label puede cambiar) usa el data-jz-action-id estable o JZ.actionById().
El campo "Buscar" filtra el árbol de directorios. Lógica de coincidencia:
La coincidencia es case-insensitive, el resaltado en amarillo muestra el punto de coincidencia.
Tras hacer clic en el icono de la extensión en la toolbar de Chrome aparece el widget del popup con un gran interruptor verde/gris "Plugin enabled". En el modo deshabilitado no se inyecta ningún CSS/JS en ninguna página, con independencia de los ajustes de los directorios. El botón flotante queda entonces deshabilitado (Halt Red, opacity 0.7). El estado sobrevive al reinicio de Chrome.
Un botón junto al campo del patrón de URL — inserta protocol://host/* de la pestaña activa. Creación de un directorio en 2 segundos. La dirección de la página de opciones de la extensión se omite — toma la pestaña externa más reciente.
Inline, a la derecha del campo de URL, aparece la información "Coincide con X pestañas abiertas" o una advertencia. Detecta erratas al instante.
Se crea una instantánea del CSS y el JS 3 segundos después de la última edición (debounce). Límite de 5 versiones — la más antigua se descarta. Al restaurar una versión, el contenido actual se añade al historial como la instantánea más reciente, de modo que siempre puedes deshacer el deshacer.
En la cabecera de la tarjeta del conjunto hay un campo para etiquetas — escríbelas separadas por comas. Aparecen como pequeñas etiquetas en el sidebar junto al nombre del conjunto. El buscador también encuentra por etiquetas.
Cada directorio puede tener su propia etiqueta en el botón flotante (máx. 3 letras, MAYÚSCULAS) y un color (selector de color). La etiqueta y el color ayudan a reconocer visualmente qué proyecto está activo en cada página.
Cada botón de acción cuenta cuántas veces se ha pulsado. Ayuda a ver cuáles se usan realmente.
Bajo el editor de CSS se muestra una barra con la lista de problemas de sintaxis:
/* ... */})} (con el número de línea)Es una validación sintáctica simple — no comprueba la corrección de properties/values. El CSS con error se sigue inyectando (el navegador simplemente omitirá las reglas erróneas).
En el modal de importación de un directorio individual, tras cargar el archivo, aparece una lista de conjuntos con métricas:
Contenido del archivo (3 conjuntos):
Auto-login CSS: 0L • JS: 4L JS
Ocultar banner cookie CSS: 8L • JS: 0L
Debug GTM CSS: 0L • JS: 12L • 2 acciones (8L) JS
Una advertencia con el número de líneas de JS si hay alguna presente. El clic en el botón JS muestra el código completo para revisarlo antes de importar.
Cada conjunto de JS se ejecuta por separado, con su propio try/catch. Un error en un conjunto no bloquea la ejecución de los demás. Los errores se registran en la consola con el nombre del conjunto/acción y el stack trace completo.
Un indicador del consumo de memoria en el menú Ajustes del sidebar (p. ej. 1.2 MB / 10 MB). Rojo por encima del 80%.
Un checkbox sobre la lista — oculta los conjuntos marcados como independientes (○) y muestra solo los activos en el directorio (●). Ayuda a filtrar los conjuntos "manuales" cuando el directorio tiene muchos. Reacciona al instante a los cambios de los interruptores.
La extensión tiene una clave fija en el manifest (en la versión para Firefox — un gecko.id fijo), lo que significa que el ID de la extensión es invariable entre actualizaciones — los datos (directorios, conjuntos, ajustes) se conservan. JustZix se distribuye para cuatro navegadores: Chrome, Edge, Opera y Firefox.
En el menú Ajustes (junto al número de versión) aparece un banner verde "Hay una nueva versión disponible" cuando el servidor publica un paquete más reciente que el instalado. El banner contiene un enlace de descarga. La comprobación es silenciosa — sin red el banner simplemente no se muestra.
chrome://extensions/ (Edge: edge://extensions/) localiza la extensión y haz clic en el icono de recarga en la tarjetaLa versión para Firefox se carga mediante about:debugging → "Este Firefox" → "Cargar complemento temporal" (apuntando a manifest.json en la carpeta justzix_firefox/). Una actualización = recargar tras sobrescribir los archivos.
"key" del manifest (Chromium) / gecko.id (Firefox)/* Ocultar anuncios típicos */
.ad, .ads, .advertisement,
.banner-ad, [class*="ad-banner"],
[id*="google_ads"] {
display: none !important;
}
/* Ocultar el cookie banner */
.cookie-banner, #cookie-notice {
display: none !important;
}
html {
filter: invert(0.92) hue-rotate(180deg);
}
img, video, picture, iframe, [style*="background-image"] {
filter: invert(1) hue-rotate(180deg);
}
Truco: invertir toda la página y volver a invertir las imágenes. Funciona sorprendentemente bien en la mayoría de páginas.
/* Colorea todos los elementos con data-testid */
[data-testid] {
outline: 2px dashed #f59e0b !important;
outline-offset: -2px;
}
[data-testid]::before {
content: attr(data-testid);
position: absolute;
background: #f59e0b;
color: white;
font-size: 10px;
padding: 2px 4px;
z-index: 9999;
}
/* Aumenta la legibilidad de las tablas del admin */
table.admin-list td, table.admin-list th {
padding: 8px 12px !important;
font-size: 14px !important;
}
/* Sticky header de la tabla */
table.admin-list thead {
position: sticky;
top: 0;
background: white;
z-index: 10;
}
/* Filas alternas */
table.admin-list tbody tr:nth-child(odd) {
background: #f9fafb;
}
/* A menudo las páginas tienen un max-width rígido de 1200px - fuerza la anchura */
.container, .main-content, main {
max-width: 95% !important;
width: 95% !important;
}
body::before {
content: "ENTORNO DEV";
position: fixed;
top: 0;
left: 0;
right: 0;
background: #dc2626;
color: white;
text-align: center;
padding: 4px;
font-weight: bold;
z-index: 999999;
font-family: 'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
}
body { padding-top: 28px !important; }
Perfecto para el patrón https://dev.example.com/* y no confundir entornos.
// ¡Solo para dev! Nunca guardes contraseñas reales
window.addEventListener('load', () => {
const login = document.querySelector('input[name="login"]');
const pass = document.querySelector('input[name="password"]');
if (login) login.value = 'admin@dev.local';
if (pass) pass.value = 'devpass123';
});
// Intercepta dataLayer.push (GTM)
const origPush = window.dataLayer?.push;
if (origPush) {
window.dataLayer.push = function(...args) {
console.log('%c[GTM]', 'color:#16a34a;font-weight:bold', args);
return origPush.apply(window.dataLayer, args);
};
}
// Intercepta gtag
const origGtag = window.gtag;
if (origGtag) {
window.gtag = function(...args) {
console.log('%c[GA4]', 'color:#2563eb;font-weight:bold', args);
return origGtag.apply(window, args);
};
}
Ideal para depurar la configuración de la analítica en producción sin tocar el código.
// Cada 500ms durante 10s comprueba y haz clic en los botones "Aceptar"
let attempts = 0;
const interval = setInterval(() => {
if (++attempts > 20) return clearInterval(interval);
const buttons = [...document.querySelectorAll('button, a')];
const target = buttons.find(b =>
/aceptar|acepto|accept all/i.test(b.textContent || '')
);
if (target) {
target.click();
clearInterval(interval);
}
}, 500);
document.addEventListener('keydown', (e) => {
// Ctrl+Shift+S - guardar el formulario
if (e.ctrlKey && e.shiftKey && e.key === 'S') {
e.preventDefault();
document.querySelector('button[type="submit"]')?.click();
}
// Ctrl+Shift+E - ir a la edición (ejemplo no probado)
if (e.ctrlKey && e.shiftKey && e.key === 'E') {
e.preventDefault();
document.querySelector('a.edit-link')?.click();
}
});
// Omite los molestos confirm y beforeunload durante las pruebas
window.confirm = () => true;
window.alert = (msg) => console.log('[alert silenciado]', msg);
window.onbeforeunload = null;
window.addEventListener('beforeunload', e => {
e.stopImmediatePropagation();
}, true);
// Recuerda - el CSS puro no lo hará cuando el padre tiene display:none
window.addEventListener('load', () => {
const target = document.querySelector('.important-info');
const newParent = document.querySelector('.sidebar');
if (target && newParent) {
newParent.prepend(target);
}
});
// Muestra todos los input type="hidden" ocultos
document.querySelectorAll('input[type="hidden"]').forEach(input => {
const wrapper = document.createElement('div');
wrapper.style.cssText = 'background:#fef3c7;padding:4px;font-size:11px;font-family:monospace;border:1px dashed #f59e0b;';
wrapper.innerHTML = `${input.name}: ${input.value}`;
input.parentNode.insertBefore(wrapper, input);
});
Etiqueta: CLR Color: rojo
document.querySelectorAll('input, textarea, select').forEach(el => {
if (el.type === 'hidden') return;
if (el.type === 'checkbox' || el.type === 'radio') {
el.checked = false;
} else {
el.value = '';
}
el.dispatchEvent(new Event('change', { bubbles: true }));
});
Etiqueta: FILL Color: verde
const data = {
email: 'test@example.com',
phone: '600000000',
firstName: 'Juan',
lastName: 'Prueba',
street: 'Calle de Prueba 1',
city: 'Madrid',
zip: '28001'
};
Object.keys(data).forEach(name => {
const el = document.querySelector(`[name="${name}"]`);
if (el) {
el.value = data[name];
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
}
});
Etiqueta: CART Color: naranja
// Para una tienda típica — haz clic en el primer "añadir al carrito"
const btn = document.querySelector('.add-to-cart, [data-action="add-to-cart"]');
if (btn) btn.click();
else alert('No se encontró el botón de añadir al carrito');
Etiqueta: COPY Color: morado
navigator.clipboard.writeText(location.href).then(() => {
console.log('Copiado:', location.href);
});
Etiqueta: TKN Color: amarillo
// Extrae el token JWT de localStorage / cookies para depurar
const token = localStorage.getItem('authToken')
|| document.cookie.match(/token=([^;]+)/)?.[1];
if (token) {
navigator.clipboard.writeText(token);
alert('Token copiado. Primeros caracteres: ' + token.slice(0, 20) + '...');
} else {
alert('No hay token');
}
Etiqueta: SQL Color: azul
// Intercepta todos los fetch y muéstralos en la consola
const origFetch = window.fetch;
window.fetch = async function(...args) {
console.log('%c[FETCH]', 'color:#2563eb', args[0]);
const res = await origFetch.apply(this, args);
return res;
};
console.log('Registro de fetch habilitado. Cada llamada aparecerá en la consola.');
Etiqueta: ENV Color: gris
const info = {
url: location.href,
userAgent: navigator.userAgent.split(' ').pop(),
cookies: document.cookie.split(';').length,
localStorage: Object.keys(localStorage).length,
framework: window.React ? 'React' : window.Vue ? 'Vue' : window.jQuery ? 'jQuery' : 'unknown'
};
alert(JSON.stringify(info, null, 2));
Cada proyecto tiene su propio directorio con su propio patrón de URL. Puedes tener directorios:
https://dev.justzix.com/* con un banner rojo "DEV"En el panel derecho los directorios privados se pueden habilitar/deshabilitar rápidamente. La exportación de un directorio individual permite compartir la configuración con el equipo.
En cada dev/staging añade un banner y auto-login. Un conjunto de CSS (el banner) y uno de JS (auto-fill). Creas un directorio aparte para cada entorno, se activan con un simple checkbox.
Un panel de acciones con botones: FILL (datos de prueba), CART (compra de prueba), CLR (vaciar el formulario), STATE (mostrar el estado de la aplicación en un alert). Sin programador, sin consola, un solo clic.
Tus blogs/documentaciones favoritos con mejor legibilidad — contenedor más ancho, fuente, modo oscuro. Cada página en un directorio aparte, "Activo" dejado siempre habilitado.
Un conjunto por cada dominio con JS que intercepta dataLayer.push y gtag. Lo habilitas cuando el cliente reporta un problema con la analítica, sin tocar el código de la página.
El patrón *://*.justzix.com/admin/* y CSS que mejora las tablas, listas y formularios. Más una acción "Filtro de prueba" que establece automáticamente los filtros para un workflow típico.
La acción RO (read-only) inyecta CSS que oculta todos los botones "Eliminar", "Guardar", "Enviar" — un "modo de solo lectura" temporal para no equivocarse.
// Oculta los botones peligrosos
document.querySelectorAll(
'button[type="submit"], .delete-btn, .danger-btn, [class*="delete"]'
).forEach(b => b.style.display = 'none');
console.warn('MODO READ-ONLY habilitado');
[JustZix] JS error!important o selectores más específicos.css-1abcd que cambian. Usa atributos ([data-testid]) o selectores establesLa extensión tiene una clave fija en el manifest — las sucesivas actualizaciones conservan los datos. Si aun así los datos desaparecieron:
chrome://extensions/ usa el botón de recarga, no elimines ni reinstalesEs normal — las posiciones son por ventana del navegador y se almacenan en la memoria de sesión (chrome.storage.session). Tras cerrar la ventana las posiciones desaparecen, en una ventana nueva empiezas desde las predeterminadas. La posición sobrevive a la navegación entre pestañas de la misma ventana.
Sí — la exportación parcial contiene solo los directorios y conjuntos marcados, más los ajustes de visibilidad relacionados con ellos. No contiene las posiciones de los paneles flotantes (son por ventana) ni otras preferencias globales. Para un backup completo usa el modo "Todo".
El modo "Fusionar" empareja los directorios por ID. Si el archivo importado tenía un ID en conflicto con un directorio existente (p. ej. el mismo archivo ya se importó una vez), aparece un prompt: 1 sobrescribir / 2 copia (predeterminado, seguro) / Cancelar. Eligiendo 2 obtienes copias con nuevos ID y el añadido "(import)" en el nombre de la carpeta — no pierdes nada.
La flecha de despliegue aparece solo si el directorio tiene conjuntos. Un directorio vacío tiene un punto atenuado en lugar de flecha. El estado de despliegue de cada directorio se recuerda en chrome.storage.local.
Esos botones están en la barra del directorio (en la parte superior del área de edición), junto al botón "Eliminar directorio". No confundir con los botones del menú Ajustes, que afectan a la totalidad de los ajustes.
El JS de reglas y acciones se ejecuta en el contexto de la página mediante una estrategia por capas resistente a las reglas estrictas de Content Security Policy. La mayoría de las páginas — incluidos grandes servicios como Facebook — funcionan de inmediato, sin configuración.
Las páginas con una CSP muy estricta (algunos bancos, sitios corporativos) pueden bloquear la ejecución. Para que el JS funcione en todas las páginas, activa para JustZix la opción «Permitir scripts de usuario»: abre chrome://extensions, ve a los detalles de JustZix y activa el interruptor (los navegadores más antiguos también requieren el modo de desarrollador). Cuando una página bloquea la ejecución, la ventana JavaScript / la Consola JS muestra un mensaje adecuado.
JustZix — manual