TableOn
Mostra artigos do WordPress e tipos de conteúdo personalizados como tabelas ordenáveis e filtráveis, construídas a partir de um construtor de colunas.
- Primeira versão
- Instalações ativas
- 200+
- Classificação
- Ler avaliações
Sobre
O TableOn renderiza artigos de qualquer tipo de conteúdo como uma tabela. O administrador constrói tabelas a partir de colunas predefinidas (título, miniatura, autor, datas, número de comentários, taxonomias, galeria) e de campos meta de artigos, acrescenta um formulário de filtros, subconjuntos predefinidos e skins, e coloca o resultado com um shortcode, num popup ou dentro de outro site através de um iframe.
Do ponto de vista da engenharia, são duas partes. No servidor, um endpoint ajax público transforma a definição de uma tabela e um estado de filtros numa WP_Query e devolve as linhas como JSON. No navegador, uma classe de tabela sem dependências pagina, ordena e pesquisa, quer por ajax quer sobre dados já carregados, e passa a um esquema compacto em ecrãs estreitos.
As partes difíceis são transformar uma definição de tabela configurável numa WP_Query para qualquer tipo de conteúdo, tipar campos meta que o WordPress guarda como strings, e manter independentes numa mesma página várias tabelas com skins e idiomas diferentes.
TableOn · tabela de artigos
o que foi resolvido
Perfis de colunas e o endpoint de consulta
shipped · 2020O que ofereceA equipa decide que colunas uma tabela mostra e que artigos inclui, e cada coluna pode ser ordenada e filtrada da mesma forma.
- Problema
- Um endpoint ajax serve as linhas de todas as tabelas: qualquer tipo de conteúdo, colunas meta definidas pelo administrador, filtros, subconjuntos predefinidos e ordenações. O mesmo campo tem de renderizar uma célula, ordenar a consulta e funcionar como filtro.
- Solução
Uma tabela é descrita por um perfil: um array de chaves de campos, cada uma com closures para o valor da célula, os argumentos da consulta e os dados do widget de filtro. As colunas pedidas são procuradas nesse perfil pela chave.
- Stack
Uma definição de campo tem de controlar a célula, a ordenação e o filtroOs campos pedidos apenas indexam o perfil; cada chave traz as suas próprias closures
TABLEON_Default::action() devolve o perfil: para cada chave, um título, uma closure 'action' que renderiza a célula e, para as chaves filtráveis, get_filter_query_args e get_filter_draw_data. get_table_data() percorre os campos pedidos e chama $profile[$field]['action'] apenas quando a chave existe, pelo que um nome de campo desconhecido é ignorado. Cada linha transporta também pid, que as ações de célula no front-end utilizam.
Os campos meta definidos pelo administrador precisam de comportamento de consulta tipadoLinhas meta do tipo texto, número ou calendário; cada tipo constrói a sua própria meta_query
assemble_meta_for_system() transforma uma linha da tabela de meta numa entrada do perfil. O texto usa LIKE e um campo de texto. O número usa BETWEEN com tipo numérico a partir de um valor 'min:max', um slider de intervalo e ordenação por meta_value_num. O calendário compara como timestamp unix (numérico) ou como DATETIME, escolhido por campo, porque plugins como o ACF guardam strings de data enquanto outros guardam timestamps.
Algumas ordenações não são exprimíveis como argumentos de WP_QueryClosure temporária em posts_orderby para post_status, removida logo após a consulta
A ordenação por post_status é feita com uma closure ligada a posts_orderby durante uma única WP_Query e removida depois, para que não passe para outras consultas na página. Os valores da lista pendente de ordenação, como title-desc ou <meta_key>-desc, são mapeados para orderby/order, com meta_value_num para campos meta tipados como número.
Tabelas limitadas a um subconjunto escolhido de artigosAs regras de predefinição tornam-se post__in, post__not_in, author__in e tax_query
Cada tabela pode guardar regras: IDs de artigos, IDs excluídos, autores, termos a incluir ou excluir. get_table_data() aplica-as antes dos filtros do visitante, com os IDs convertidos para inteiros. Um atributo de shortcode author=N é incorporado nas mesmas regras (comentário no código datado de 16-09-2020).
A configuração da tabela não se ajusta bem à post metaQuatro tabelas próprias via dbDelta: tabelas, colunas, campos meta, vocabulário
As colunas são linhas com table_id, field_key, pos_num, is_active, show_on_mobile e opções em JSON, indexadas em table_id e is_active, pelo que as colunas ativas de uma tabela são uma única consulta indexada. A configuração inteira exporta-se como um documento JSON; a importação esvazia cada tabela e volta a inserir as linhas, atrás de uma verificação de função.
Formulário de filtros sobre artigos e meta
shipped · 2020O que ofereceOs visitantes restringem as tabelas por texto, categorias, intervalos de números e datas. Os limites dos sliders acompanham os dados reais, pelo que a equipa não tem de os introduzir.
- Problema
- O formulário de filtros é gerado a partir do mesmo perfil para qualquer tipo de conteúdo: pesquisa de texto, árvores de taxonomia, intervalos numéricos e intervalos de datas. O plugin não tem índice próprio, pelo que os limites e as opções têm de vir de dados reais.
- Solução
Cada chave de filtro fornece dados de desenho (limites, opções, rótulos) e um construtor de consultas. Os limites numéricos vêm de consultas MIN/MAX, a menos que o administrador os tenha definido. As condições que a WP_Query não consegue exprimir passam por posts_where: os valores de texto têm escape e são preparados, as datas são formatadas com date() e as contagens convertidas com intval().
- Stack
Pesquisa de texto em colunas escolhidas, sem distinção de maiúsculas, seguraposts_where com LOWER(field) LIKE; campos em lista de permissões, valores preparados e esc_like
As colunas pesquisáveis vêm do atributo de shortcode tableon_text_search_by mas são filtradas para post_title, post_content e post_excerpt, pelo que um nome de coluna nunca chega ao SQL a partir de fora da lista. O termo é convertido para minúsculas com um auxiliar compatível com multibyte, escapado com esc_like() e ligado com $wpdb->prepare().
Os sliders de intervalo precisam de limites que o administrador não introduziuOs limites por omissão são MIN/MAX de CAST(meta_value AS UNSIGNED) para a chave meta
get_field_drawing_data() usa o mínimo/máximo guardado da tabela quando definido; caso contrário, consulta wp_postmeta pela chave com uma conversão numérica, para que números guardados como texto se comparem como números. Os limites do número de comentários são MIN/MAX sobre wp_posts do tipo de conteúdo da tabela.
Um campo de data precisa de dois campos de entrada, de e atéDesenhar uma chave gémea com o sufixo ---to; o provider encaminha-a com uma flag de direção
draw_filter_form_data() duplica um campo de calendário como <key>---to com os rótulos 'From:' e 'To:'. A chave não existe no perfil, pelo que provider() reconhece o sufixo, remove-o e chama o construtor de consultas do campo original com is_calendar_dir_to = true, o que inverte >= para <=.
O multisselect de taxonomia precisa de IN, NOT IN ou AND por tabelaOperador guardado por tabela, verificado contra uma lista de permissões antes de tax_query
A opção mselect-logic é lida das opções de filtro da tabela e substituída por IN se não for uma de IN, NOT IN, AND. Os IDs de termos entram em tax_query por term_id.
Listas hierárquicas de termos com conjuntos de inclusão e exclusãoÁrvore recursiva por pai com um prefixo de profundidade, filtrada por listas de IDs
build_taxonomy_tree() percorre os termos pai a pai, ignora os IDs excluídos, mantém apenas os IDs incluídos quando essa lista está definida, e prefixa os títulos com um traço por nível, para que um select simples mostre a hierarquia. Executa uma chamada get_terms() por pai com hide_empty.
Outros plugins de filtro têm de poder controlar a mesma tabelaO hook de provider tableon_filter_provider_{name} reescreve os argumentos da WP_Query
O pedido indica um filter provider; get_table_data() passa os argumentos da consulta, os dados do filtro e os argumentos do shortcode pelo filtro correspondente. O formulário incorporado é o provider 'default'. O Taxonomy Chain Menu usa o lado do cliente disto, escrevendo filter_data na tabela e pedindo-lhe que redesenhe.
Motor de tabela no lado do cliente
shipped · 2020O que oferecePaginar, ordenar e pesquisar parecem rápidos porque os dados já carregados são reutilizados, e as tabelas largas passam a um esquema compacto em telemóveis.
- Problema
- As tabelas correm em páginas, popups e iframes e têm de paginar, ordenar e pesquisar sem esperar pelo servidor a cada clique. Cliques rápidos fazem as respostas chegar fora de ordem, e as tabelas largas não cabem em telemóveis.
- Solução
Uma classe JavaScript sem dependências com três modos de dados, um motor SQL no navegador para as linhas carregadas, uma cache por pedido, cancelamento de pedidos e um esquema compacto abaixo de uma largura configurável.
- Stack
Uma resposta anterior lenta não deve sobrescrever uma página mais recenteO AbortController cancela o fetch anterior antes de um novo pedido começar
Cada pedido ajax guarda o seu AbortController; um novo pedido aborta primeiro o pendente, pelo que só o estado mais recente de página, ordenação ou filtro é desenhado.
Ordenar e paginar dados que já estão no navegadorO modo json executa SELECT, ORDER BY e LIMIT do AlaSQL sobre as linhas carregadas
No modo json, as linhas vêm embebidas na página. A pesquisa por título, a contagem, ORDER BY e LIMIT/OFFSET são construídos como strings SQL e executados pelo AlaSQL sobre o array em memória, pelo que paginar e ordenar não precisam de pedidos.
Carregar por ajax uma vez e depois deixar de fazer viagens de ida e voltaModo to_json: a primeira resposta ajax torna-se dados locais e o modo passa a json
to_json começa como ajax com uma flag de mudança. Após a primeira resposta, as linhas são mantidas como table_data e o modo passa a json. No servidor, os modos json pedem todos os artigos correspondentes (posts_per_page = -1), o que o código assinala como risco de memória, pelo que o modo se adequa a conjuntos pequenos e médios.
Pedidos repetidos para páginas já vistasGuardar as respostas em cache sob um hash de 32 bits do objeto de pedido JSON
set_cache() e get_cache() indexam as respostas por __hash_object(request_data), um hash de string sobre JSON.stringify do pedido inteiro (página, ordem, filtros). Voltar a uma página já vista é servido a partir da memória. A cache está desligada nos modos json, to_json e load-more, onde os dados são locais de qualquer forma.
Tabelas largas em telemóveisVista compacta abaixo de uma largura definida, ocultação de colunas por coluna em dispositivos móveis, redimensionamento com throttle
Abaixo de compact_view_width, as linhas são desenhadas como células empilhadas e os cabeçalhos ficam ocultos. O handler de redimensionamento só redesenha quando o estado compacto realmente muda e bloqueia-se durante 999 ms entre execuções. As colunas podem ser retiradas em dispositivos móveis (hide_on_mobile) ou ocultadas abaixo de uma largura em píxeis por regras @media geradas. As linhas são construídas num DocumentFragment e inseridas de uma só vez.
Incorporação, isolamento e acesso à administração
no produtoO que ofereceVárias tabelas com estilos diferentes podem partilhar uma página, as tabelas podem ser mostradas noutros sites, os rótulos seguem o idioma do site, e funções de equipa escolhidas podem geri-las.
- Problema
- Várias tabelas com skins diferentes podem partilhar uma página, uma tabela pode ser incorporada noutro site, os rótulos têm de seguir o idioma do site, e a gestão de tabelas não se limita a administradores.
- Solução
O CSS é delimitado ao id HTML de cada tabela no momento da renderização, a incorporação remota passa por um script carregador gerado, os rótulos passam por uma tabela de tradução e os ecrãs de administração são controlados por uma definição de função.
- Stack
Várias tabelas com skins diferentes numa páginaO CSS da skin usa um marcador 'tid' substituído pelo id HTML da tabela, e depois é minificado
get_theme_css() carrega a skin primeiro da pasta tableon-skins do tema e depois do plugin, substitui tid pelo id HTML da tabela, remove comentários e espaços em branco. Os estilos por coluna e o CSS personalizado da tabela também são prefixados com #<table id>, para que as regras de uma tabela não toquem noutra.
Mostrar uma tabela num site que não é WordPressO script carregador constrói um iframe lazy para uma página que usa o template em branco do plugin
Um pedido com tableon-remote-page e anchor devolve JavaScript em vez de uma página: as definições como variáveis mais remote.js, que cria um iframe de carregamento lazy no contentor indicado. A página lá dentro usa um template em branco que o plugin regista, pelo que a estrutura do tema não é mostrada.
A configuração JSON em linha não deve sair do seu contentor HTMLjson_encode com JSON_HEX_TAG, JSON_HEX_QUOT e JSON_HEX_AMP num div oculto
As definições da tabela e, no modo json, todas as linhas são impressas na página. Codificar <, >, aspas e & como escapes unicode significa que títulos de artigos ou valores meta não podem fechar o elemento nem injetar markup.
Textos da interface em vários idiomas sem ficheiros .poUma tabela de vocabulário mapeia uma string para valores por idioma, carregada uma vez por pedido
TABLEON_Vocabulary lê a tabela inteira uma vez para um array estático; get() devolve o valor para o locale atual ou a string original. O idioma atual passa pelo filtro tableon_current_lang, que também muda o WPML, pelo que os pedidos ajax são renderizados no idioma do visitante.
Editores que não são administradores gerem tabelascan_manage_data(): administrador ou funções definidas nas definições, mais um nonce em cada gravação
Os ecrãs de administração só são registados para utilizadores que passam can_manage_data(), que aceita administradores e as funções listadas na definição user_roles_can. Os handlers de gravação, criação e eliminação verificam cada um o nonce 'tableon'.
Números
wordpress.org- Instalações ativas 200+ contador do wordpress.org.
- Avaliações 15 Média de 4.6 em 5.
- Anos de suporte 6 Desde 2 de novembro de 2020, última atualização em 12 de junho de 2026.