nur-sery/nur_src/v/bs3/plugins/navtabPlugin.php

183 lines
4.6 KiB
PHP

<?php
namespace nur\v\bs3\plugins;
use nur\A;
use nur\func;
use nur\v\BasePlugin;
use nur\v\js;
use nur\v\v;
use nur\v\vo;
class navtabPlugin extends BasePlugin {
const COD_KEY = null;
const TITLE_KEY = null;
const FRAGMENT_PREFIX = "#nt:";
/** @var array liste de tableaux [cod, title] */
private $tabs;
/** @var array liste des codes valides */
private $tabCods;
function __construct(?array $tabs=null) {
$this->setTabs($tabs);
}
protected function filterTab($tab, ?array $tabs=null): bool {
return false;
}
protected function getCod($tab): string {
$codKey = static::COD_KEY;
$tab = A::with($tab);
if ($codKey !== null) return A::get($tab, $codKey, "");
return A::first($tab, "");
}
protected function getTitle($tab): ?string {
$titleKey = static::TITLE_KEY;
$tab = A::with($tab);
if ($titleKey !== null) return A::get($tab, $titleKey);
else return A::second($tab);
}
private function getCodTitle($tab): array {
$cod = $this->getCod($tab);
$title = $this->getTitle($tab);
if ($title == null) $title = $cod;
return [$cod, $title];
}
function setTabs(?array $tabs=null): void {
$tabs = A::with($tabs);
$filteredTabs = [];
$tabCods = [];
foreach ($tabs as $tab) {
if ($this->filterTab($tab, $tabs)) continue;
$filteredTabs[] = $tab;
$tabCods[] = $this->getCod($tab);
}
$this->tabs = $filteredTabs;
$this->tabCods = $tabCods;
}
const HAVE_JQUERY = true;
protected function jqSetup(): void {}
protected function jqBeforeDeactivate(): void {}
protected function jqAfterActivate(): void {}
function printJquery(): void {
$tabCods = $this->tabCods;
if (!$tabCods) return;
?>
<script type="text/javascript">
<?php $this->jqSetup(); ?>
var NAV_TABS = <?=js::qvs($tabCods)?>;
function activateTab(activeTab) {
<?php $this->jqBeforeDeactivate(); ?>
for (let i in NAV_TABS) {
let tab = NAV_TABS[i];
if (tab === activeTab) continue;
$("#" + tab + "_tab").removeClass("active");
$("#" + tab + "_panel").addClass("hide");
}
$("#" + activeTab + "_panel").removeClass("hide");
$("#" + activeTab + "_tab").addClass("active");
<?php $this->jqAfterActivate(); ?>
}
<?php foreach ($tabCods as $tabCod): ?>
$(<?=js::qv("#${tabCod}_tab")?>).click(function() {
activateTab(<?=js::qv($tabCod)?>);
return false;
});
<?php endforeach; ?>
function updateTab(initial=false) {
let prefix = <?=js::qv(static::FRAGMENT_PREFIX)?>;
let hash = window.location.hash;
let hashOk = false;
if (hash.startsWith(prefix)) {
let tab = hash.slice(prefix.length);
if ($("#" + tab + "_tab").length) {
activateTab(tab);
hashOk = true;
}
}
if (!hashOk && initial) {
for (let i in NAV_TABS) {
let tab = NAV_TABS[i];
if ($("#" + tab + "_tab").length) {
activateTab(tab);
break;
}
}
}
}
$(window).on("hashchange", function() {
updateTab();
});
updateTab(true);
</script>
<?php
}
const URL_KEY = null;
protected function getUrl($tab): ?string {
$urlKey = static::URL_KEY;
if ($urlKey !== null) return A::get($tab, $urlKey);
else return null;
}
const BADGE_KEY = null;
protected function getBadge($tab): ?string {
$badgeKey = static::BADGE_KEY;
if ($badgeKey !== null) return A::get($tab, $badgeKey);
else return null;
}
function paTabs(?string $curCod=null): void {
$tabs = $this->tabs;
if (!$tabs) return;
vo::sul(["class" => "nav nav-tabs"]);
foreach ($tabs as $tab) {
[$cod, $title] = $this->getCodTitle($tab);
vo::li([
"id" => "${cod}_tab",
"class" => $cod === $curCod? "active": null,
"role" => "presentation",
v::a([
"href" => $this->getUrl($tab),
q($title),
v::span(["class" => "badge", $this->getBadge($tab)])
]),
]);
}
vo::eul();
}
function paStartPanel($cod): void {
if (!is_string($cod)) $cod = $this->getCod($cod);
vo::sdiv(["id" => "${cod}_panel"]);
}
function paEndPanel(): void {
vo::ediv();
}
function printActions(?string $curCod, callable $printPanel, ?callable $beforePanels=null, ?callable $afterPanels=null): bool {
$tabs = $this->tabs;
if (!$tabs) return false;
$func = func::_prepare($printPanel);
$this->paTabs($curCod);
if ($beforePanels !== null) $beforePanels();
foreach ($this->tabs as $tab) {
$this->paStartPanel($tab);
func::_call($func, [$tab, $this]);
$this->paEndPanel();
}
if ($afterPanels !== null) $afterPanels();
return true;
}
}