--- /dev/null
+<?php
+$fields = ["Nom", "Email", "Âge"];
+$data = [
+ ["Alice", "alice@example.com", 25],
+ ["Bob", "bob@example.com", 30],
+ ["Charlie", "charlie@example.com", 22],
+];
+?>
+<!DOCTYPE html>
+<html lang="fr">
+<head>
+<meta charset="UTF-8">
+<title>Tableau filtrable "super débile écoeurant"</title>
+<style>
+table { border-collapse: collapse; width: 60%; margin-top: 10px; }
+th, td { border: 1px solid #000; padding: 6px 12px; text-align: left; cursor: pointer; transition: background-color 0.3s; }
+th.selected { background-color: #ffd700; color: #000; }
+td span.highlight { background-color: #ff4; font-weight: bold; }
+input { width: 60%; padding: 6px; font-size: 16px; }
+</style>
+</head>
+<body>
+
+<h2>Recherche filtrable “Super, débile, écoeurante” 😎</h2>
+
+<input type="text" id="searchInput" placeholder="Tapez pour filtrer...">
+
+<table id="myTable">
+ <thead>
+ <tr>
+ <?php foreach($fields as $field): ?>
+ <th><?= htmlspecialchars($field) ?></th>
+ <?php endforeach; ?>
+ </tr>
+ </thead>
+ <tbody>
+ <?php foreach($data as $row): ?>
+ <tr>
+ <?php foreach($row as $cell): ?>
+ <td><?= htmlspecialchars($cell) ?></td>
+ <?php endforeach; ?>
+ </tr>
+ <?php endforeach; ?>
+ </tbody>
+</table>
+
+<script>
+// --- Setup ---
+const input = document.getElementById('searchInput');
+const table = document.getElementById('myTable');
+const rows = table.tBodies[0].rows;
+const headers = table.tHead.rows[0].cells;
+let activeCols = new Set([0]); // colonne(s) active(s) par défaut
+
+// --- Gestion du clic sur les en-têtes ---
+for (let i = 0; i < headers.length; i++) {
+ headers[i].addEventListener('click', () => {
+ if (activeCols.has(i)) {
+ activeCols.delete(i);
+ headers[i].classList.remove('selected');
+ } else {
+ activeCols.add(i);
+ headers[i].classList.add('selected');
+ }
+ filterTable();
+ });
+}
+
+// --- Fonction de filtrage et highlight ---
+input.addEventListener('input', filterTable);
+
+function filterTable() {
+ const query = input.value.toLowerCase();
+
+ for (let row of rows) {
+ let match = false;
+ for (let i = 0; i < row.cells.length; i++) {
+ const cell = row.cells[i];
+ const text = cell.textContent;
+
+ if (activeCols.has(i) && text.toLowerCase().includes(query) && query !== "") {
+ // highlight
+ const regex = new RegExp(`(${escapeRegExp(query)})`, 'gi');
+ cell.innerHTML = text.replace(regex, '<span class="highlight">$1</span>');
+ match = true;
+ } else {
+ // reset
+ cell.textContent = text;
+ }
+ }
+ row.style.display = match || query === "" ? '' : 'none';
+ }
+}
+
+// --- Fonction helper pour regex ---
+function escapeRegExp(string) {
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+}
+
+// --- Initialisation visuelle ---
+for (let i of activeCols) headers[i].classList.add('selected');
+</script>
+
+</body>
+</html>
+
--- /dev/null
+<?php
+$fields = ["Nom", "Email", "Âge"];
+$data = [
+ ["Alice", "alice@example.com", 25],
+ ["Bob", "bob@example.com", 30],
+ ["Charlie", "charlie@example.com", 22],
+];
+?>
+<!DOCTYPE html>
+<html lang="fr">
+<head>
+<meta charset="UTF-8">
+<title>Tableau Filtrable Ultime 😎</title>
+<style>
+body { font-family: sans-serif; }
+table { border-collapse: collapse; width: 60%; margin-top: 10px; }
+th, td { border: 1px solid #000; padding: 6px 12px; text-align: left; cursor: pointer; transition: background-color 0.3s, transform 0.2s; }
+th.selected { background-color: #ff9800; color: #fff; }
+td span.highlight { font-weight: bold; transition: background-color 0.3s; }
+input { width: 60%; padding: 6px; font-size: 16px; margin-bottom: 10px; }
+
+/* Confetti effect */
+.confetti { position: absolute; width: 6px; height: 6px; background-color: red; animation: confetti-fall 1s linear forwards; z-index: 1000; border-radius: 50%; }
+@keyframes confetti-fall { 0% { transform: translateY(0) rotate(0deg); opacity: 1; } 100% { transform: translateY(100px) rotate(360deg); opacity: 0; } }
+</style>
+</head>
+<body>
+
+<h2>Recherche “Ultime, Écoeurante, Joyeuse” 😎</h2>
+<input type="text" id="searchInput" placeholder="Tapez pour filtrer...">
+
+<table id="myTable">
+ <thead>
+ <tr>
+ <?php foreach($fields as $field): ?>
+ <th><?= htmlspecialchars($field) ?></th>
+ <?php endforeach; ?>
+ </tr>
+ </thead>
+ <tbody>
+ <?php foreach($data as $row): ?>
+ <tr>
+ <?php foreach($row as $cell): ?>
+ <td><?= htmlspecialchars($cell) ?></td>
+ <?php endforeach; ?>
+ </tr>
+ <?php endforeach; ?>
+ </tbody>
+</table>
+
+<script>
+const input = document.getElementById('searchInput');
+const table = document.getElementById('myTable');
+const rows = table.tBodies[0].rows;
+const headers = table.tHead.rows[0].cells;
+
+// Colonne active par défaut
+let activeCols = new Set([0]);
+
+// Palette dynamique pour highlight par colonne
+const colors = ["#ffeb3b","#8bc34a","#03a9f4","#e91e63","#9c27b0"];
+
+// --- clic sur en-tête pour sélectionner/désélectionner colonnes ---
+for (let i = 0; i < headers.length; i++) {
+ headers[i].addEventListener('click', () => {
+ if (activeCols.has(i)) {
+ activeCols.delete(i);
+ headers[i].classList.remove('selected');
+ } else {
+ activeCols.add(i);
+ headers[i].classList.add('selected');
+ }
+ filterTable();
+ });
+}
+
+// --- filtrage et highlight ---
+input.addEventListener('input', filterTable);
+
+function filterTable() {
+ const query = input.value.toLowerCase();
+
+ for (let row of rows) {
+ let match = false;
+ for (let i = 0; i < row.cells.length; i++) {
+ const cell = row.cells[i];
+ const text = cell.textContent;
+
+ if (activeCols.has(i) && text.toLowerCase().includes(query) && query !== "") {
+ const regex = new RegExp(`(${escapeRegExp(query)})`, 'gi');
+ cell.innerHTML = text.replace(regex, `<span class="highlight" style="background-color:${colors[i % colors.length]}">$1</span>`);
+ match = true;
+ } else {
+ cell.textContent = text;
+ }
+ }
+ row.style.display = match || query === "" ? '' : 'none';
+ if (match && query !== "") {
+ triggerConfetti(row);
+ row.style.transform = "scale(1.02)";
+ setTimeout(()=>row.style.transform="scale(1)",200);
+ }
+ }
+}
+
+// --- helper regex ---
+function escapeRegExp(string) {
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+}
+
+// --- confetti ---
+function triggerConfetti(row) {
+ for (let i=0;i<5;i++){
+ const conf = document.createElement('div');
+ conf.className = 'confetti';
+ conf.style.left = (row.getBoundingClientRect().left + Math.random()*row.offsetWidth) + 'px';
+ conf.style.top = (row.getBoundingClientRect().top + window.scrollY) + 'px';
+ conf.style.backgroundColor = colors[Math.floor(Math.random()*colors.length)];
+ document.body.appendChild(conf);
+ setTimeout(()=>conf.remove(),1000);
+ }
+}
+
+// --- initialisation ---
+for (let i of activeCols) headers[i].classList.add('selected');
+</script>
+
+</body>
+</html>
+
--- /dev/null
+<?php
+// ----------------------
+// Fichier PHP principal
+// ----------------------
+
+// Données du tableau
+$fields = ["Nom", "Email", "Âge"];
+$data = [
+ ["Alice", "alice@example.com", 25],
+ ["Bob", "bob@example.com", 30],
+ ["Charlie", "charlie@example.com", 22],
+];
+
+// Génération du HTML des en-têtes
+function generateTableHeader(array $fields): string {
+ $html = '';
+ foreach ($fields as $field) {
+ $html .= "<th>" . htmlspecialchars($field) . "</th>";
+ }
+ return $html;
+}
+
+// Génération du HTML du corps
+function generateTableBody(array $data): string {
+ $html = '';
+ foreach ($data as $row) {
+ $html .= "<tr>";
+ foreach ($row as $cell) {
+ $html .= "<td>" . htmlspecialchars($cell) . "</td>";
+ }
+ $html .= "</tr>";
+ }
+ return $html;
+}
+
+// Injection des contenus dans des variables
+$tableHeaderHTML = generateTableHeader($fields);
+$tableBodyHTML = generateTableBody($data);
+?>
+
+<!DOCTYPE html>
+<html lang="fr">
+<head>
+<meta charset="UTF-8">
+<title>Tableau filtrable Super</title>
+<style>
+table { border-collapse: collapse; width: 50%; margin-top: 10px; }
+th, td { border: 1px solid #000; padding: 4px 8px; text-align: left; cursor: pointer; }
+th.selected { background-color: #cce5ff; }
+td span.highlight { background-color: #ffeb3b; font-weight: bold; }
+input.filter-input { width: 50%; padding: 4px; margin-bottom: 8px; font-size: 14px; }
+</style>
+</head>
+<body>
+
+<h2>Tableau filtrable “Super”</h2>
+
+<input type="text" class="filter-input" placeholder="Tapez pour filtrer...">
+
+<table class="filter-table">
+ <thead>
+ <tr><?= $tableHeaderHTML ?></tr>
+ </thead>
+ <tbody>
+ <?= $tableBodyHTML ?>
+ </tbody>
+</table>
+
+<script>
+// Classe générique pour filtrer un tableau avec multi-colonnes
+class TableFilter {
+ constructor(tableElement, inputElement) {
+ this.table = tableElement;
+ this.input = inputElement;
+ this.rows = tableElement.tBodies[0].rows;
+ this.headers = tableElement.tHead.rows[0].cells;
+ this.activeCols = new Set([0]); // colonne(s) active(s) par défaut
+
+ this.init();
+ }
+
+ init() {
+ for (let i = 0; i < this.headers.length; i++) {
+ this.headers[i].addEventListener('click', () => {
+ // toggle colonne active
+ if (this.activeCols.has(i)) {
+ this.activeCols.delete(i);
+ this.headers[i].classList.remove('selected');
+ } else {
+ this.activeCols.add(i);
+ this.headers[i].classList.add('selected');
+ }
+ this.filter();
+ });
+ }
+
+ this.input.addEventListener('input', () => this.filter());
+
+ // Initialisation visuelle
+ for (let i of this.activeCols) this.headers[i].classList.add('selected');
+ }
+
+ filter() {
+ const query = this.input.value.toLowerCase();
+
+ for (let row of this.rows) {
+ let match = false;
+
+ for (let i = 0; i < row.cells.length; i++) {
+ const cell = row.cells[i];
+ const text = cell.textContent;
+
+ if (this.activeCols.has(i) && query && text.toLowerCase().includes(query)) {
+ const regex = new RegExp(`(${this.escapeRegExp(query)})`, 'gi');
+ cell.innerHTML = text.replace(regex, '<span class="highlight">$1</span>');
+ match = true;
+ } else {
+ cell.textContent = text; // reset highlight
+ }
+ }
+
+ // Affichage : au moins une colonne correspond
+ row.style.display = match || query === "" ? '' : 'none';
+ }
+ }
+
+ escapeRegExp(string) {
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ }
+}
+
+// Instanciation générique pour tous les tableaux
+document.querySelectorAll('.filter-table').forEach(table => {
+ const input = document.querySelector('.filter-input');
+ new TableFilter(table, input);
+});
+</script>
+
+</body>
+</html>
+
global $isadmin;
global $myfilename;
+$originator=gettranslate($userlang,"Originator");
+$recipient=gettranslate($userlang,"Recipient");
+$date=gettranslate($userlang,"Date");
+
$limit=20;
$offset=0;
$dsearch="";
-$selectedField = 'rcptto';
+$selectedField = $recipient;
if (isset($_POST['limit']))
$limit=intval($_POST['limit']);
$dsearch=trim($_POST['dsearch']);
if (strlen($dsearch)>0) {
// sécuriser le champ sélectionné
- $allowedFields = ['smtpfrom','rcptto','creation'];
+ $allowedFields = [$originator,$recipient,$date];
if (!in_array($selectedField,$allowedFields))
$selectedField = 'rcptto';
if ($limit>30)
$tblfooter=$tblheader;
-$originator=gettranslate($userlang,"Originator");
-$recipient=gettranslate($userlang,"Recipient");
-$date=gettranslate($userlang,"Date");
-
$STR = <<<EOT
$start