TableOn
Muestra entradas de WordPress y tipos de contenido personalizados como tablas ordenables y filtrables creadas con un constructor de columnas.
- Primera versión
- Instalaciones activas
- 200+
- Valoración
- Leer reseñas
Sobre mí
TableOn renderiza las entradas de cualquier tipo de contenido como una tabla. El administrador construye tablas a partir de columnas predefinidas (título, miniatura, autor, fechas, número de comentarios, taxonomías, galería) y de campos meta de la entrada, añade un formulario de filtros, subconjuntos predefinidos y skins, y coloca el resultado con un shortcode, en una ventana emergente o dentro de otro sitio mediante un iframe.
Desde el punto de vista de la ingeniería son dos partes. En el servidor, un endpoint ajax público convierte la definición de una tabla y un estado de filtros en una WP_Query y devuelve las filas como JSON. En el navegador, una clase de tabla sin dependencias pagina, ordena y busca, ya sea mediante ajax o sobre datos ya cargados, y cambia a un diseño compacto en pantallas estrechas.
Las partes difíciles son convertir una definición de tabla configurable en una WP_Query para cualquier tipo de contenido, tipar los campos meta que WordPress almacena como cadenas y mantener independientes varias tablas con distintos skins e idiomas en una misma página.
TableOn · tabla de entradas
qué se resolvió
Perfiles de columnas y el endpoint de consulta
shipped · 2020Qué aportaEl personal decide qué columnas muestra una tabla y qué entradas incluye, y cada columna puede ordenarse y filtrarse de la misma manera.
- Problema
- Un endpoint ajax sirve las filas de todas las tablas: cualquier tipo de contenido, columnas meta definidas por el administrador, filtros, subconjuntos predefinidos y órdenes de clasificación. El mismo campo tiene que renderizar una celda, ordenar la consulta y actuar como filtro.
- Solución
Una tabla se describe mediante un perfil: un array de claves de campo, cada una con closures para el valor de la celda, los argumentos de la consulta y los datos del widget de filtro. Las columnas solicitadas se buscan en ese perfil por clave.
- Stack
Una definición de campo debe controlar la celda, la ordenación y el filtroLos campos solicitados solo indexan el perfil; cada clave trae sus propios closures
TABLEON_Default::action() devuelve el perfil: para cada clave, un título, un closure 'action' que renderiza la celda y, para las claves filtrables, get_filter_query_args y get_filter_draw_data. get_table_data() recorre los campos solicitados y llama a $profile[$field]['action'] solo cuando la clave existe, así que un nombre de campo desconocido se ignora. Cada fila también lleva pid, que usan las acciones de celda en el front-end.
Los campos meta definidos por el administrador necesitan un comportamiento de consulta tipadoFilas meta de tipo texto, número o calendario; cada tipo construye su propia meta_query
assemble_meta_for_system() convierte una fila de la tabla meta en una entrada del perfil. El texto usa LIKE y un campo de texto. El número usa BETWEEN con tipo numeric a partir de un valor 'min:max', un slider de rango y ordenación por meta_value_num. El calendario compara como marca de tiempo unix (numérica) o como DATETIME, según el campo, porque plugins como ACF almacenan cadenas de fecha mientras que otros almacenan marcas de tiempo.
Algunos órdenes de clasificación no se pueden expresar como argumentos de WP_QueryClosure temporal de posts_orderby para post_status, eliminado justo después de la consulta
La ordenación por post_status se hace con un closure enganchado a posts_orderby durante una sola WP_Query y eliminado después, de modo que no se filtra a otras consultas de la página. Los valores del desplegable de ordenación como title-desc o <meta_key>-desc se asignan a orderby/order, con meta_value_num para los campos meta de tipo número.
Tablas limitadas a un subconjunto elegido de entradasLas reglas de predefinición se convierten en post__in, post__not_in, author__in y tax_query
Cada tabla puede almacenar reglas: IDs de entradas, IDs excluidos, autores, términos a incluir o excluir. get_table_data() las aplica antes de los filtros del visitante, con los IDs convertidos a enteros. Un atributo de shortcode author=N se incorpora a las mismas reglas (comentario del código con fecha 16-09-2020).
La configuración de la tabla no encaja bien en los metadatos de entradaCuatro tablas propias mediante dbDelta: tablas, columnas, campos meta, vocabulario
Las columnas son filas con table_id, field_key, pos_num, is_active, show_on_mobile y opciones JSON, indexadas por table_id e is_active, de modo que las columnas activas de una tabla se obtienen con una sola consulta indexada. Toda la configuración se exporta como un único documento JSON; la importación vacía cada tabla y reinserta las filas, tras una comprobación de rol.
Formulario de filtros sobre entradas y metadatos
shipped · 2020Qué aportaLos visitantes acotan las tablas por texto, categorías, rangos numéricos y fechas. Los límites de los sliders siguen los datos reales, así que el personal no tiene que introducirlos.
- Problema
- El formulario de filtros se genera a partir del mismo perfil para cualquier tipo de contenido: búsqueda de texto, árboles de taxonomía, rangos numéricos y rangos de fechas. El plugin no tiene un índice propio, así que los límites y las opciones deben venir de datos en vivo.
- Solución
Cada clave de filtro aporta datos de dibujo (límites, opciones, etiquetas) y un constructor de consultas. Los límites numéricos proceden de consultas MIN/MAX salvo que el administrador los haya establecido. Las condiciones que WP_Query no puede expresar pasan por posts_where: los valores de texto se escapan y se preparan, las fechas se formatean con date() y los recuentos se convierten con intval().
- Stack
Búsqueda de texto en las columnas elegidas, sin distinguir mayúsculas y seguraposts_where con LOWER(field) LIKE; campos en lista blanca, valores preparados y esc_like
Las columnas en las que se puede buscar proceden del atributo de shortcode tableon_text_search_by, pero se filtran a post_title, post_content y post_excerpt, de modo que un nombre de columna nunca llega al SQL desde fuera de la lista. El término se pasa a minúsculas con una función auxiliar compatible con multibyte, se escapa con esc_like() y se enlaza con $wpdb->prepare().
Los sliders de rango necesitan límites que el administrador no introdujoLos límites por defecto son MIN/MAX de CAST(meta_value AS UNSIGNED) para la clave meta
get_field_drawing_data() usa el mínimo y el máximo almacenados de la tabla cuando están establecidos; si no, consulta wp_postmeta por la clave con una conversión numérica, de modo que los números almacenados como texto se comparan como números. Los límites del número de comentarios son MIN/MAX sobre wp_posts del tipo de contenido de la tabla.
Un campo de fecha necesita dos entradas, desde y hastaDibujar una clave gemela con el sufijo ---to; el proveedor la enruta con una marca de dirección
draw_filter_form_data() duplica un campo de calendario como <key>---to con las etiquetas 'From:' y 'To:'. La clave no existe en el perfil, así que provider() reconoce el sufijo, lo elimina y llama al constructor de consultas del campo original con is_calendar_dir_to = true, que cambia >= por <=.
La selección múltiple de taxonomías necesita IN, NOT IN o AND por tablaOperador almacenado por tabla, comprobado contra una lista blanca antes de tax_query
La opción mselect-logic se lee de las opciones de filtro de la tabla y se sustituye por IN si no es una de IN, NOT IN, AND. Los IDs de término van a tax_query por term_id.
Listas jerárquicas de términos con conjuntos de inclusión y exclusiónÁrbol recursivo por padre con un prefijo de profundidad, filtrado por listas de IDs
build_taxonomy_tree() recorre los términos padre por padre, omite los IDs excluidos, conserva solo los IDs incluidos cuando esa lista está establecida y antepone a los títulos un guion por nivel para que un select plano muestre la jerarquía. Ejecuta una llamada a get_terms() por padre con hide_empty.
Otros plugins de filtros deben poder controlar la misma tablaEl hook de proveedor tableon_filter_provider_{name} reescribe los argumentos de WP_Query
La petición nombra un proveedor de filtros; get_table_data() pasa los argumentos de la consulta, los datos del filtro y los argumentos del shortcode por el filtro correspondiente. El formulario integrado es el proveedor 'default'. Taxonomy Chain Menu usa la parte cliente de esto, escribiendo filter_data en la tabla y pidiéndole que se redibuje.
Motor de tabla en el cliente
shipped · 2020Qué aportaLa paginación, la ordenación y la búsqueda resultan rápidas porque se reutilizan los datos ya cargados, y las tablas anchas pasan a un diseño compacto en los teléfonos.
- Problema
- Las tablas se ejecutan en páginas, ventanas emergentes e iframes y deben paginar, ordenar y buscar sin esperar al servidor en cada clic. Los clics rápidos hacen que las respuestas lleguen desordenadas, y las tablas anchas no caben en los teléfonos.
- Solución
Una clase de JavaScript sin dependencias con tres modos de datos, un motor SQL en el navegador para las filas cargadas, una caché por petición, cancelación de peticiones y un diseño compacto por debajo de un ancho configurable.
- Stack
Una respuesta anterior y lenta no debe sobrescribir una página más recienteAbortController cancela el fetch anterior antes de que empiece una nueva petición
Cada petición ajax almacena su AbortController; una nueva petición aborta primero la pendiente, así que solo se dibuja el estado más reciente de página, ordenación o filtro.
Ordenar y paginar datos que ya están en el navegadorEl modo json ejecuta SELECT, ORDER BY y LIMIT de AlaSQL sobre las filas cargadas
En el modo json las filas vienen incrustadas en la página. La búsqueda por título, el recuento, ORDER BY y LIMIT/OFFSET se construyen como cadenas SQL y AlaSQL las ejecuta sobre el array en memoria, así que la paginación y la ordenación no necesitan peticiones.
Cargar por ajax una vez y después dejar de hacer viajes de ida y vueltaModo to_json: la primera respuesta ajax se convierte en datos locales y el modo cambia a json
to_json empieza como ajax con una marca de cambio. Tras la primera respuesta, las filas se conservan como table_data y el modo pasa a ser json. En el servidor, los modos json solicitan todas las entradas coincidentes (posts_per_page = -1), lo que el código marca como un riesgo de memoria, así que el modo es adecuado para conjuntos pequeños y medianos.
Peticiones repetidas de páginas ya vistasGuardar las respuestas en caché bajo un hash de 32 bits del objeto de petición JSON
set_cache() y get_cache() indexan las respuestas por __hash_object(request_data), un hash de cadena sobre JSON.stringify de toda la petición (página, orden, filtros). Volver a una página ya vista se sirve desde la memoria. La caché está desactivada en los modos json, to_json y load-more, donde los datos son locales de todos modos.
Tablas anchas en teléfonosVista compacta por debajo de un ancho establecido, ocultación de columnas en móvil por columna, resize con limitación de frecuencia
Por debajo de compact_view_width, las filas se dibujan como celdas apiladas y se ocultan las cabeceras. El manejador de resize solo redibuja cuando el estado compacto cambia realmente y se bloquea a sí mismo durante 999 ms entre ejecuciones. Las columnas pueden omitirse en móvil (hide_on_mobile) u ocultarse por debajo de un ancho en píxeles mediante reglas @media generadas. Las filas se construyen en un DocumentFragment y se insertan una sola vez.
Incrustación, aislamiento y acceso de administración
en el productoQué aportaVarias tablas con estilos distintos pueden compartir una página, las tablas pueden mostrarse en otros sitios web, las etiquetas siguen el idioma del sitio y los roles de personal elegidos pueden gestionarlas.
- Problema
- Varias tablas con distintos skins pueden compartir una página, una tabla puede incrustarse en otro sitio, las etiquetas deben seguir el idioma del sitio y la gestión de tablas no se limita a los administradores.
- Solución
El CSS se acota al id HTML de cada tabla en el momento del renderizado, la incrustación remota pasa por un script cargador generado, las etiquetas pasan por una tabla de traducción y las pantallas de administración se controlan mediante un ajuste de roles.
- Stack
Varias tablas con distintos skins en una misma páginaEl CSS del skin usa un marcador 'tid' sustituido por el id HTML de la tabla y después se minifica
get_theme_css() carga primero el skin desde la carpeta tableon-skins del tema y después desde el plugin, sustituye tid por el id HTML de la tabla y elimina comentarios y espacios en blanco. Los estilos por columna y el CSS personalizado de la tabla también llevan el prefijo #<table id>, de modo que las reglas de una tabla no afectan a otra.
Mostrar una tabla en un sitio que no es WordPressEl script cargador construye un iframe diferido que apunta a una página que usa la plantilla en blanco del plugin
Una petición con tableon-remote-page y anchor devuelve JavaScript en lugar de una página: ajustes como variables más remote.js, que crea un iframe de carga diferida en el contenedor indicado. La página interior usa una plantilla en blanco que registra el plugin, así que no se muestra el marco del tema.
La configuración JSON en línea no debe salirse de su contenedor HTMLjson_encode con JSON_HEX_TAG, JSON_HEX_QUOT y JSON_HEX_AMP en un div oculto
Los ajustes de la tabla y, en el modo json, todas las filas se imprimen en la página. Codificar <, >, las comillas y & como escapes unicode significa que los títulos de entradas o los valores meta no pueden cerrar el elemento ni inyectar marcado.
Cadenas de interfaz en varios idiomas sin archivos .poUna tabla de vocabulario asigna una cadena a valores por idioma, cargada una vez por petición
TABLEON_Vocabulary lee toda la tabla una vez en un array estático; get() devuelve el valor del idioma actual o la cadena original. El idioma actual pasa por el filtro tableon_current_lang, que también cambia WPML, de modo que las peticiones ajax se renderizan en el idioma del visitante.
Editores que no son administradores gestionan tablascan_manage_data(): administrador o roles de los ajustes, más un nonce en cada guardado
Las pantallas de administración se registran solo para los usuarios que pasan can_manage_data(), que acepta administradores y los roles indicados en el ajuste user_roles_can. Los manejadores de guardar, crear y eliminar verifican cada uno el nonce 'tableon'.
Cifras
wordpress.org- Instalaciones activas 200+ contador de wordpress.org.
- Reseñas 15 Media de 4.6 sobre 5.
- Años de soporte 6 Desde 2 de noviembre de 2020, última actualización 12 de junio de 2026.