return function () {
$self = url('/@object/@action/' . urlencode('table/bs5_components'));
$data = json_decode(file_get_contents(__DIR__ . '/products.json'), true);
// The active flags live in the visitor's session (the sample rows start with a few inactive ones), never in a table
$key = 'docs_demo_bs5_components_active';
if ( ! isset($_SESSION[$key]) || ! is_array($_SESSION[$key])) {
$_SESSION[$key] = [];
foreach ($data as $id => $row) {
$_SESSION[$key][(int) $id] = (int) $row['viewed'] >= 1000 ? 1 : 0;
}
}
$toggle = (int) ($_GET['toggle'] ?? 0);
if ($toggle && isset($_SESSION[$key][$toggle])) {
$_SESSION[$key][$toggle] = (int) ! $_SESSION[$key][$toggle];
// the answer of the framework's active handlers: "1" / "0" for ajax, a redirect otherwise
if (is_ajax()) {
no_graphics(true);
echo $_SESSION[$key][$toggle];
exit;
}
return js_redirect($self);
}
foreach ($data as $id => $row) {
$data[$id]['active'] = $_SESSION[$key][(int) $id] ?? 0;
}
$actions = ['edit', 'view', 'clone', 'delete'];
$act = in_array($_GET['act'] ?? '', $actions, true) ? $_GET['act'] : '';
$notice = $act ? '<div class="alert alert-info">Row button <b>' . $act . '</b> of row <b>' . (int) ($_GET['row'] ?? 0) . '</b> was clicked (the demo only shows it).</div>' : '';
$intro = '<p class="docs-demo-intro">Bootstrap 5 table options of <code>table()</code> (<code>yf_table2</code>) and
<code>html()->pagination()</code>, on the sample products. Switch the framework with <a href="' . $self . '?bs=5">?bs=5</a> /
<a href="' . $self . '?bs=3">?bs=3</a>: every option is a pure addition and falls back to Bootstrap 3 markup, and a table without
them renders exactly as before.</p>
<ul class="docs-demo-intro">
<li><code>responsive</code> => <code>true</code> or a breakpoint (<code>sm</code>, <code>md</code>, <code>lg</code>, <code>xl</code>,
<code>xxl</code>): a <code>table-responsive[-md]</code> wrapper (Bootstrap 3 has only <code>table-responsive</code>).</li>
<li><code>sticky_header</code> => <code>true</code> (sticks while the page scrolls) or a height such as <code>\'300px\'</code> (a scroll box
the header sticks in, also needed inside <code>responsive</code>): <code>thead.sticky-top</code> under bs5, inline
<code>position: sticky</code> under Bootstrap 3.</li>
<li><code>tr_variant</code> => <code>fn($row, $id)</code> returning <code>success</code>, <code>danger</code>, <code>warning</code>,
<code>info</code>, <code>active</code>...: <code>table-success</code> under bs5, <code>success</code> under Bootstrap 3, merged with the
<code>tr</code> option.</li>
<li><code>buttons_group</code> => <code>true</code> and <code>buttons_dropdown_after</code> => <code>N</code>: the row buttons in one
<code>btn-group</code>, and all after the first N in a "⋯" menu; links, classes (<code>ajax_delete</code>), rights checks stay.</li>
<li><code>btn_active(\'Active\', $link, [\'renderer\' => \'switch\'])</code>: a <code>form-switch</code> under bs5 that posts to the
same active URL (asset <code>yf_active_switch</code>); Bootstrap 3 keeps the buttons.</li>
<li><code>html()->pagination($pages, [\'current\', \'disabled\', \'size\' => \'sm|lg\', \'align\' => \'center|end\'])</code> and the
table options <code>pager_size</code> / <code>pager_align</code>.</li>
<li>Table variants need no new option: <code>table_class_add</code>, <code>thead</code> / <code>tbody</code> classes.</li>
</ul>';
// sold: many (success), few (warning), almost none (danger); an inactive row otherwise gets the `active` (grey) variant
$variant = function ($row) {
$sold = (int) $row['sold'];
if ($sold >= 900 || $sold < 300) {
return $sold >= 900 ? 'success' : ($sold < 150 ? 'danger' : 'warning');
}
return $row['active'] ? '' : 'active';
};
$wide = table($data, [
'no_pages' => 1,
'responsive' => true,
'sticky_header' => '300px',
'tr_variant' => $variant,
'table_attr' => 'id="demo-wide" style="min-width: 1400px"',
])
->text('id')
->text('name')
->text('articul')
->text('price')
->text('old_price')
->text('quantity')
->text('sold')
->text('viewed')
->date('add_date', 'Added')
->date('update_date', 'Updated')
->text('url', 'URL');
$buttons = table(array_slice($data, 0, 6, true), [
'no_pages' => 1,
'buttons_group' => true,
'buttons_dropdown_after' => 3,
'tr_variant' => $variant,
'table_attr' => 'id="demo-buttons"',
])
->text('id')
->text('name')
->text('sold')
->btn_active('Active', $self . '?toggle=%d', ['renderer' => 'switch'])
->btn_edit(['link' => $self . '?act=edit&row=%d', 'no_ajax' => 1])
->btn_view(['link' => $self . '?act=view&row=%d', 'no_ajax' => 1])
->btn_clone(['link' => $self . '?act=clone&row=%d', 'no_ajax' => 1])
->btn_delete(['link' => $self . '?act=delete&row=%d']);
$sticky = table($data, [
'no_pages' => 1,
'sticky_header' => true,
'condensed' => 1,
'table_attr' => 'id="demo-sticky"',
])
->text('id')
->text('name')
->text('price')
->text('sold');
$variants = table(array_slice($data, 0, 4, true), [
'no_pages' => 1,
'caption' => 'table-striped-columns, caption-top, a table-dark head and a table-group-divider body',
'table_class_add' => 'table-striped-columns caption-top',
'thead' => ['class' => 'table-dark'],
'tbody' => ['class' => 'table-group-divider'],
])
->text('id')
->text('name')
->text('price');
$dark = table(array_slice($data, 4, 3, true), ['no_pages' => 1, 'table_class_add' => 'table-dark'])
->text('id')
->text('name')
->text('price');
$pages = ['prev' => '', 1 => $self . '?p=1', 2 => $self . '?p=2', 3 => $self . '?p=3', 4 => $self . '?p=4', 'next' => $self . '?p=3'];
$pagination = '';
foreach (['sm' => ['align' => ''], '' => ['align' => 'center'], 'lg' => ['align' => 'end']] as $size => $opts) {
$pagination .= '<p class="text-muted">size <code>' . ($size ?: 'default') . '</code>, align <code>' . ($opts['align'] ?: 'start') . '</code>,
current 2, prev disabled</p>'
. html()->pagination($pages, ['current' => 2, 'disabled' => ['prev'], 'size' => $size, 'align' => $opts['align'], 'id' => 'demo-pagination-' . ($size ?: 'md')]);
}
$paged = table($data, [
'pager_records_on_page' => 5,
'pager_size' => 'sm',
'pager_align' => 'center',
'extra' => ['url_path' => $self . '?'],
'table_attr' => 'id="demo-paged"',
])
->text('id')
->text('name')
->text('price');
return $intro . $notice
. '<h3>responsive, sticky_header (scroll box), tr_variant</h3>' . $wide
. '<h3>buttons_group, buttons_dropdown_after, active switch</h3>' . $buttons
. '<h3>sticky_header => true (page scroll)</h3>' . $sticky
. '<h3>Table variants (table_class_add, thead, tbody)</h3>' . $variants . $dark
. '<h3>html()->pagination() states and sizes</h3>' . $pagination
. '<h3>pager_size, pager_align</h3>' . $paged;
};