TableOn
Affiche les articles WordPress et les types de contenu personnalisés sous forme de tableaux triables et filtrables, construits à partir d'un constructeur de colonnes.
- Première version
- Installations actives
- 200+
- Note
- Lire les avis
À propos
TableOn restitue les articles de n'importe quel type de contenu sous forme de tableau. L'administrateur construit des tableaux à partir de colonnes prédéfinies (titre, vignette, auteur, dates, nombre de commentaires, taxonomies, galerie) et de champs post meta, ajoute un formulaire de filtre, des sous-ensembles prédéfinis et des thèmes visuels, et place le résultat avec un shortcode, dans une fenêtre contextuelle, ou à l'intérieur d'un autre site au moyen d'une iframe.
Sur le plan technique, il y a deux parties. Côté serveur, un point d'entrée ajax public transforme une définition de tableau et un état de filtre en WP_Query et retourne les lignes en JSON. Dans le navigateur, une classe de tableau sans dépendances gère la pagination, le tri et la recherche, soit par ajax, soit sur des données déjà chargées, et passe à une présentation compacte sur les écrans étroits.
Les parties difficiles sont de transformer une définition de tableau configurable en WP_Query pour n'importe quel type de contenu, de typer des champs meta que WordPress stocke sous forme de chaînes, et de garder indépendants plusieurs tableaux ayant des thèmes et des langues différents sur une même page.
TableOn · tableau d'articles
ce qui a été résolu
Profils de colonnes et point d'entrée des requêtes
shipped · 2020Ce que cela apporteLe personnel décide quelles colonnes un tableau affiche et quels articles il inclut, et chaque colonne peut être triée et filtrée de la même façon.
- Problème
- Un seul point d'entrée ajax sert les lignes de chaque tableau : n'importe quel type de contenu, colonnes meta définies par l'administrateur, filtres, sous-ensembles prédéfinis et ordres de tri. Le même champ doit rendre une cellule, trier la requête et servir de filtre.
- Solution
Un tableau est décrit par un profil : un tableau de clés de champs, chacune avec des closures pour la valeur de la cellule, les arguments de requête et les données du widget de filtre. Les colonnes demandées sont recherchées dans ce profil par clé.
- Stack
Une seule définition de champ doit piloter la cellule, le tri et le filtreLes champs demandés ne font qu'indexer le profil ; chaque clé apporte ses propres closures
TABLEON_Default::action() retourne le profil : pour chaque clé un titre, une closure 'action' qui rend la cellule, et pour les clés filtrables get_filter_query_args et get_filter_draw_data. get_table_data() parcourt les champs demandés et n'appelle $profile[$field]['action'] que si la clé existe, de sorte qu'un nom de champ inconnu est ignoré. Chaque ligne porte aussi pid, que les actions de cellule du front utilisent.
Les champs meta définis par l'administrateur exigent un comportement de requête typéLignes meta typées texte, nombre ou calendrier ; chaque type construit son propre meta_query
assemble_meta_for_system() transforme une ligne de la table meta en entrée de profil. Le texte utilise LIKE et un champ de saisie texte. Le nombre utilise BETWEEN avec le type numeric à partir d'une valeur 'min:max', un curseur de plage et un tri par meta_value_num. Le calendrier compare soit comme un horodatage unix (numérique), soit comme DATETIME, au choix par champ, car des extensions comme ACF stockent des chaînes de date tandis que d'autres stockent des horodatages.
Certains ordres de tri ne sont pas exprimables en arguments WP_QueryClosure posts_orderby temporaire pour post_status, retirée juste après la requête
Le tri par post_status se fait avec une closure accrochée à posts_orderby pendant la durée d'une WP_Query puis retirée, de sorte qu'elle ne déborde pas sur les autres requêtes de la page. Les valeurs de la liste Trier par, comme title-desc ou <meta_key>-desc, sont converties en orderby/order, avec meta_value_num pour les champs meta typés nombre.
Des tableaux limités à un sous-ensemble choisi d'articlesLes règles de prédéfinition deviennent post__in, post__not_in, author__in et tax_query
Chaque tableau peut stocker des règles : ID d'articles, ID exclus, auteurs, termes à inclure ou exclure. get_table_data() les applique avant les filtres du visiteur, avec les ID convertis en entiers. Un attribut de shortcode author=N est intégré aux mêmes règles (commentaire de code daté du 16-09-2020).
La configuration des tableaux s'accorde mal avec les post metaQuatre tables personnalisées via dbDelta : tableaux, colonnes, champs meta, vocabulaire
Les colonnes sont des lignes avec table_id, field_key, pos_num, is_active, show_on_mobile et des options JSON, indexées sur table_id et is_active, de sorte que les colonnes actives d'un tableau tiennent en une requête indexée. Toute la configuration s'exporte comme un seul document JSON ; l'import vide chaque table et réinsère les lignes, derrière un contrôle de rôle.
Formulaire de filtre sur les articles et les meta
shipped · 2020Ce que cela apporteLes visiteurs restreignent les tableaux par texte, catégories, plages de nombres et dates. Les limites des curseurs suivent les données réelles, le personnel n'a donc pas à les saisir.
- Problème
- Le formulaire de filtre est généré à partir du même profil pour n'importe quel type de contenu : recherche textuelle, arbres de taxonomies, plages numériques et plages de dates. L'extension n'a pas d'index propre, donc les bornes et les options doivent venir de données vivantes.
- Solution
Chaque clé de filtre fournit des données de dessin (bornes, options, libellés) et un constructeur de requête. Les bornes numériques viennent de requêtes MIN/MAX sauf si l'administrateur les a définies. Les conditions que WP_Query ne sait pas exprimer passent par posts_where : les valeurs texte sont échappées et préparées, les dates sont formatées avec date() et les nombres convertis avec intval().
- Stack
Recherche textuelle dans des colonnes choisies, insensible à la casse, sûreposts_where avec LOWER(field) LIKE ; champs sur liste blanche, valeurs préparées et esc_like
Les colonnes de recherche viennent de l'attribut de shortcode tableon_text_search_by mais sont filtrées sur post_title, post_content et post_excerpt, de sorte qu'un nom de colonne n'atteint jamais le SQL depuis l'extérieur de la liste. Le terme est mis en minuscules avec un utilitaire gérant le multioctet, échappé avec esc_like() et lié avec $wpdb->prepare().
Les curseurs de plage ont besoin de bornes que l'administrateur n'a pas saisiesLes bornes par défaut sont MIN/MAX de CAST(meta_value AS UNSIGNED) pour la clé meta
get_field_drawing_data() utilise le min/max stocké du tableau s'il est défini ; sinon il interroge wp_postmeta pour la clé avec une conversion numérique, de sorte que les nombres stockés en texte se comparent comme des nombres. Les bornes du nombre de commentaires sont MIN/MAX sur wp_posts pour le type de contenu du tableau.
Un champ de date a besoin de deux saisies, du et auDessiner une clé jumelle avec le suffixe ---to ; le provider l'aiguille avec un drapeau de direction
draw_filter_form_data() duplique un champ calendrier en <key>---to avec les libellés 'From:' et 'To:'. La clé n'existe pas dans le profil, donc provider() reconnaît le suffixe, le retire et appelle le constructeur de requête du champ d'origine avec is_calendar_dir_to = true, ce qui change >= en <=.
La sélection multiple de taxonomie exige IN, NOT IN ou AND par tableauOpérateur stocké par tableau, vérifié contre une liste blanche avant tax_query
L'option mselect-logic est lue dans les options de filtre du tableau et remplacée par IN si elle n'est pas l'une de IN, NOT IN, AND. Les ID de termes vont dans tax_query par term_id.
Des listes de termes hiérarchiques avec des ensembles d'inclusion et d'exclusionArbre récursif par parent avec un préfixe de profondeur, filtré par listes d'ID
build_taxonomy_tree() parcourt les termes parent par parent, ignore les ID exclus, ne garde que les ID inclus lorsque cette liste est définie, et préfixe les titres d'un tiret par niveau pour qu'un select à plat montre la hiérarchie. Il exécute un appel get_terms() par parent avec hide_empty.
D'autres extensions de filtre doivent pouvoir piloter le même tableauLe hook de provider tableon_filter_provider_{name} réécrit les arguments WP_Query
La requête nomme un provider de filtre ; get_table_data() fait passer les arguments de requête, les données de filtre et les arguments du shortcode par le filtre correspondant. Le formulaire intégré est le provider 'default'. Taxonomy Chain Menu utilise le côté client de ce mécanisme, en écrivant filter_data dans le tableau et en lui demandant de se redessiner.
Moteur de tableau côté client
shipped · 2020Ce que cela apporteLa pagination, le tri et la recherche semblent rapides parce que les données déjà chargées sont réutilisées, et les tableaux larges passent à une présentation compacte sur les téléphones.
- Problème
- Les tableaux s'exécutent dans des pages, des fenêtres contextuelles et des iframes et doivent paginer, trier et rechercher sans attendre le serveur à chaque clic. Des clics rapides font arriver les réponses dans le désordre, et les tableaux larges ne tiennent pas sur les téléphones.
- Solution
Une classe JavaScript sans dépendances avec trois modes de données, un moteur SQL dans le navigateur pour les lignes chargées, un cache par requête, l'annulation de requêtes et une présentation compacte en dessous d'une largeur configurable.
- Stack
Une réponse précédente lente ne doit pas écraser une page plus récenteAbortController annule le fetch précédent avant le démarrage d'une nouvelle requête
Chaque requête ajax stocke son AbortController ; une nouvelle requête interrompt d'abord celle en attente, de sorte que seul l'état le plus récent de page, de tri ou de filtre est dessiné.
Trier et paginer des données déjà présentes dans le navigateurLe mode json exécute AlaSQL SELECT, ORDER BY et LIMIT sur les lignes chargées
En mode json, les lignes sont intégrées à la page. La recherche dans le titre, le comptage, ORDER BY et LIMIT/OFFSET sont construits comme des chaînes SQL et exécutés par AlaSQL sur le tableau en mémoire, de sorte que la pagination et le tri ne demandent aucune requête.
Charger une fois par ajax, puis cesser les allers-retoursMode to_json : la première réponse ajax devient des données locales et le mode bascule en json
to_json démarre comme ajax avec un drapeau de bascule. Après la première réponse, les lignes sont conservées comme table_data et le mode devient json. Côté serveur, les modes json demandent tous les articles correspondants (posts_per_page = -1), ce que le code signale comme un risque mémoire, de sorte que ce mode convient aux ensembles petits et moyens.
Des requêtes répétées pour des pages déjà vuesMettre les réponses en cache sous un hachage 32 bits de l'objet de requête JSON
set_cache() et get_cache() indexent les réponses par __hash_object(request_data), un hachage de chaîne sur JSON.stringify de toute la requête (page, ordre, filtres). Revenir à une page déjà vue est servi depuis la mémoire. Le cache est désactivé dans les modes json, to_json et load-more, où les données sont de toute façon locales.
Des tableaux larges sur les téléphonesVue compacte sous une largeur donnée, masquage mobile par colonne, resize bridé
En dessous de compact_view_width, les lignes sont dessinées sous forme de cellules empilées et les en-têtes sont masqués. Le gestionnaire de resize ne redessine que lorsque l'état compact change réellement et se verrouille lui-même pendant 999 ms entre deux exécutions. Les colonnes peuvent être supprimées sur mobile (hide_on_mobile) ou masquées sous une largeur en pixels par des règles @media générées. Les lignes sont construites dans un DocumentFragment et insérées en une seule fois.
Intégration, isolation et accès à l'administration
dans le produitCe que cela apportePlusieurs tableaux de styles différents peuvent partager une page, les tableaux peuvent être affichés sur d'autres sites, les libellés suivent la langue du site, et des rôles choisis du personnel peuvent les gérer.
- Problème
- Plusieurs tableaux avec des thèmes visuels différents peuvent partager une page, un tableau peut être intégré dans un autre site, les libellés doivent suivre la langue du site, et la gestion des tableaux n'est pas réservée aux administrateurs.
- Solution
Le CSS est limité à l'id HTML de chaque tableau au moment du rendu, l'intégration à distance passe par un script de chargement généré, les libellés passent par une table de traduction, et les écrans d'administration sont protégés par un réglage de rôle.
- Stack
Plusieurs tableaux avec des thèmes visuels différents sur une même pageLe CSS du thème utilise un espace réservé 'tid' remplacé par l'id HTML du tableau, puis minifié
get_theme_css() charge le thème d'abord depuis le dossier tableon-skins du thème WordPress, puis depuis l'extension, remplace tid par l'id HTML du tableau, supprime les commentaires et les espaces. Les styles par colonne et le CSS personnalisé du tableau sont eux aussi préfixés par #<table id>, de sorte que les règles d'un tableau ne touchent pas un autre.
Afficher un tableau sur un site qui n'est pas WordPressUn script de chargement construit une iframe paresseuse vers une page qui utilise le modèle vierge de l'extension
Une requête avec tableon-remote-page et anchor retourne du JavaScript au lieu d'une page : les réglages sous forme de variables plus remote.js, qui crée une iframe à chargement différé dans le conteneur indiqué. La page à l'intérieur utilise un modèle vierge que l'extension enregistre, de sorte que l'habillage du thème n'est pas affiché.
La configuration JSON en ligne ne doit pas s'échapper de son conteneur HTMLjson_encode avec JSON_HEX_TAG, JSON_HEX_QUOT et JSON_HEX_AMP dans un div masqué
Les réglages du tableau et, en mode json, toutes les lignes sont imprimés dans la page. Encoder <, >, les guillemets et & en échappements unicode empêche les titres d'articles ou les valeurs meta de fermer l'élément ou d'injecter du balisage.
Des chaînes d'interface en plusieurs langues sans fichiers .poUne table de vocabulaire associe une chaîne à des valeurs par langue, chargée une fois par requête
TABLEON_Vocabulary lit toute la table une fois dans un tableau statique ; get() retourne la valeur pour la locale courante ou la chaîne d'origine. La langue courante passe par le filtre tableon_current_lang, qui bascule aussi WPML, de sorte que les requêtes ajax sont rendues dans la langue du visiteur.
Des éditeurs autres que les administrateurs gèrent les tableauxcan_manage_data() : administrateur ou rôles issus des réglages, plus un nonce à chaque enregistrement
Les écrans d'administration ne s'enregistrent que pour les utilisateurs qui passent can_manage_data(), qui accepte les administrateurs et les rôles listés dans le réglage user_roles_can. Les gestionnaires d'enregistrement, de création et de suppression vérifient chacun le nonce 'tableon'.
Chiffres
wordpress.org- Installations actives 200+ compteur de wordpress.org.
- Avis 15 Moyenne de 4.6 sur 5.
- Années de maintenance 6 Depuis 2 novembre 2020, dernière mise à jour 12 juin 2026.