19 declare(strict_types=1);
53 if ($component instanceof
MainBar) {
54 return $this->renderMainbar($component, $default_renderer);
56 if ($component instanceof
MetaBar) {
57 return $this->renderMetabar($component, $default_renderer);
59 if ($component instanceof
Footer) {
60 return $this->
renderFooter($component, $default_renderer);
62 if ($component instanceof
ModeInfo) {
73 if (!$slate instanceof
Slate && !$slate instanceof
MainBar) {
77 ->withMainBarTreePosition($pos)
79 function ($num, $slate, $is_tool =
false) use ($pos) {
98 $is_removeable = array_key_exists($entry_id, $close_buttons);
99 $is_hidden = in_array($entry_id, $hidden);
101 if ($is_removeable) {
102 $trigger_signal = $component->getTriggerSignal($mb_id, $component::ENTRY_ACTION_REMOVE);
103 $this->trigger_signals[] = $trigger_signal;
104 $btn_removetool = $close_buttons[$entry_id]
105 ->withAdditionalOnloadCode(
106 fn(
$id) =>
"il.UI.maincontrols.mainbar.addPartIdAndEntry('$mb_id', 'remover', '$id', true);" 108 ->withOnClick($trigger_signal);
110 $tpl->setCurrentBlock(
"tool_removal");
111 $tpl->setVariable(
"REMOVE_TOOL", $default_renderer->render($btn_removetool));
112 $tpl->parseCurrentBlock();
115 $is_removeable = $is_removeable ?
'true' :
'false';
116 $is_hidden = $is_hidden ?
'true' :
'false';
117 return "il.UI.maincontrols.mainbar.addToolEntry('$mb_id', $is_removeable, $is_hidden, '$entry_id');";
128 foreach ($entries as $k => $entry) {
133 if ($entry instanceof
Slate) {
135 $mb_id = $entry->getMainBarTreePosition();
136 $is_tool = $block === static::BLOCK_MAINBAR_TOOLS;
138 $js = $this->
renderToolEntry($k, $mb_id, $component, $tpl, $default_renderer);
141 $trigger_signal = $component->getTriggerSignal($mb_id, $component::ENTRY_ACTION_TRIGGER);
142 $this->trigger_signals[] = $trigger_signal;
143 $button =
$f->button()->bulky($entry->getSymbol(), $entry->getName(),
'#')
144 ->withOnClick($trigger_signal)
145 ->withHelpTopics(...$entry->getHelpTopics());
148 $pos = array_search($k, array_keys($entries));
149 $mb_id =
'0:' . $pos;
153 $button = $button->withAdditionalOnLoadCode(
154 function (
$id) use ($js, $mb_id, $k, $is_tool):
string {
155 $add_as_tool = $is_tool ?
'true' :
'false';
157 il.UI.maincontrols.mainbar.addPartIdAndEntry('$mb_id', 'triggerer', '$id', $add_as_tool); 158 il.UI.maincontrols.mainbar.addMapping('$k','$mb_id'); 162 )->withAriaRole(IBulky::MENUITEM);
164 $tpl->setCurrentBlock($block);
165 $tpl->setVariable(
"BUTTON", $default_renderer->render($button));
166 $tpl->parseCurrentBlock();
169 $entry = $entry->withAriaRole(ISlate::MENU);
171 $tpl->setCurrentBlock(
"slate_item");
172 $tpl->setVariable(
"SLATE", $default_renderer->render($entry));
173 $tpl->parseCurrentBlock();
181 $tpl = $this->
getTemplate(
"tpl.mainbar.html",
true,
true);
183 $tpl->setVariable(
"ARIA_LABEL", $this->
txt(
'mainbar_aria_label'));
184 $more_btn_label = $this->
txt(
'mainbar_more_label');
188 $more_slate =
$f->mainControls()->slate()->combined(
190 $f->symbol()->glyph()->more()
192 $more_slate = $more_slate->withAriaRole(ISlate::MENU);
200 static::BLOCK_MAINBAR_ENTRIES => $component->
getEntries(),
204 foreach ($mb_entries as $block => $entries) {
219 $tpl->setCurrentBlock(
"tools_trigger");
220 $tpl->setVariable(
"BUTTON", $default_renderer->render($btn_tools));
221 $tpl->parseCurrentBlock();
225 $btn_disengage =
$f->button()->bulky(
$f->symbol()->glyph()->collapseHorizontal(
"#"), $this->
txt(
'close'),
"#")
227 $tpl->setVariable(
"CLOSE_SLATES", $default_renderer->render($btn_disengage));
231 $tpl->setVariable(
'ID',
$id);
239 $tpl = $this->
getTemplate(
"tpl.metabar.html",
true,
true);
247 $more_label = $this->
txt(
'show_more');
248 $more_symbol =
$f->symbol()->glyph()->disclosure()
249 ->withCounter(
$f->counter()->novelty(0))
250 ->withCounter(
$f->counter()->status(0));
254 $more_slate =
$f->mainControls()->slate()->combined($more_label, $more_symbol);
255 $more_slate = $more_slate->withAriaRole(ISlate::MENU);
256 $entries[] = $more_slate;
262 static::BLOCK_METABAR_ENTRIES,
268 function (
$id) use ($signals) {
269 $entry_signal = $signals[
'entry'];
270 $close_slates_signal = $signals[
'close_slates'];
272 il.UI.maincontrols.metabar.init('$id'); 273 il.UI.maincontrols.metabar.get('$id').registerSignals( 275 '$close_slates_signal', 277 il.UI.maincontrols.metabar.get('$id').init(); 278 window.addEventListener( 280 ()=>{il.UI.maincontrols.metabar.get('$id').init()} 285 $tpl->setVariable(
'ARIA_LABEL', $this->
txt(
'metabar_aria_label'));
288 $tpl->setVariable(
'ID',
$id);
294 $tpl = $this->
getTemplate(
"tpl.mode_info.html",
true,
true);
295 $tpl->setVariable(
'MODE_TITLE', $component->
getModeTitle());
298 $action = $base_URI .
'?' . $query;
299 $close = $this->
getUIFactory()->symbol()->glyph()->close($action);
300 $tpl->setVariable(
'CLOSE_GLYPH', $default_renderer->render($close));
309 $tpl = $this->
getTemplate(
"tpl.system_info.html",
true,
true);
310 $tpl->setVariable(
'HEADLINE', $component->getHeadLine());
311 $tpl->setVariable(
'BODY', $component->getInformationText());
312 $tpl->setVariable(
'DENOTATION', $component->getDenotation());
313 switch ($component->getDenotation()) {
316 $tpl->setVariable(
'LIVE',
'aria-live="polite"');
319 $tpl->setVariable(
'ROLE',
'role="alert"');
322 if ($component->isDismissable()) {
323 $close = $this->
getUIFactory()->symbol()->glyph()->close(
"#");
324 $signal = $component->getCloseSignal();
325 $close = $close->withOnClick($signal);
326 $tpl->setVariable(
'CLOSE_BUTTON', $default_renderer->render($close));
327 $tpl->setVariable(
'CLOSE_URI', (
string) $component->getDismissAction());
328 $component = $component->withAdditionalOnLoadCode(fn(
$id) =>
"$(document).on('$signal', function() { il.UI.maincontrols.system_info.close('$id'); });");
331 $more = $this->
getUIFactory()->symbol()->glyph()->more(
"#");
332 $tpl->setVariable(
'MORE_BUTTON', $default_renderer->render($more));
334 $component = $component->withAdditionalOnLoadCode(fn(
$id) =>
"il.UI.maincontrols.system_info.init('$id')");
337 $tpl->setVariable(
'ID',
$id);
338 $tpl->setVariable(
'ID_HEADLINE',
$id .
"_headline");
339 $tpl->setVariable(
'ID_DESCRIPTION',
$id .
"_description");
351 ?
string $active =
null 353 foreach ($entries as
$id => $entry) {
357 if ($entry instanceof
Slate) {
359 $secondary_signal = $entry->getToggleSignal();
360 $clickable =
$f->button()->bulky($entry->getSymbol(), $entry->getName(),
'#')
362 ->withOnClick($entry_signal)
363 ->appendOnClick($secondary_signal)
364 ->withAriaRole(IBulky::MENUITEM)
365 ->withHelpTopics(...$entry->getHelpTopics());
368 } elseif ($entry instanceof
IBulky) {
370 $clickable = $clickable->withAriaRole(IBulky::MENUITEM);
376 $clickable_html = $default_renderer->render($clickable);
379 $tpl->setCurrentBlock(
"slate_item");
380 $tpl->setVariable(
"SLATE", $default_renderer->render($slate));
381 $tpl->parseCurrentBlock();
384 $tpl->setCurrentBlock($use_block);
385 $tpl->setVariable(
"BUTTON", $clickable_html);
386 $tpl->parseCurrentBlock();
394 $inititally_active = $component->
getActive();
397 function (
$id) use ($component, $trigger_signals, $inititally_active):
string {
401 $js =
"il.UI.maincontrols.mainbar.addTriggerSignal('$disengage_all_signal');";
402 $js .=
"il.UI.maincontrols.mainbar.addTriggerSignal('$tools_toggle_signal');";
404 foreach ($trigger_signals as $signal) {
405 $js .=
"il.UI.maincontrols.mainbar.addTriggerSignal('$signal');";
410 $js .=
"il.UI.maincontrols.mainbar.addTriggerSignal('$signal');";
414 window.addEventListener('resize', il.UI.maincontrols.mainbar.adjustToScreenSize); 415 il.UI.maincontrols.mainbar.init('$inititally_active'); 430 $template = $this->
getTemplate(
"tpl.footer.html",
true,
true);
433 $permanent_url = $component->getPermanentURL();
434 if (
null !== $permanent_url) {
435 $template->setCurrentBlock(
'with_additional_item');
436 $template->setVariable(
'ITEM_CONTENT', $this->
permanentLink((
string) $permanent_url, $default_renderer));
437 $template->parseCurrentBlock();
442 $additional_link_groups = $component->getAdditionalLinkGroups();
443 if ([] !== $additional_link_groups) {
445 foreach ($additional_link_groups as [$title, $actions]) {
446 $link_groups[] = [$this->
getUIFactory()->listing()->unordered($actions), $title];
453 $this->
txt(
'footer_link_groups'),
459 $additional_links = $component->getAdditionalLinks();
460 if ([] !== $additional_links) {
461 $links =
array_map(
static fn($link) => [$link,
null], $additional_links);
466 $this->
txt(
'footer_links'),
472 $additional_icons = $component->getAdditionalIcons();
473 if ([] !== $additional_icons) {
475 foreach ($additional_icons as [$icon, $action]) {
476 if (
null !== $action) {
477 if ($action instanceof
URI) {
478 $action = (string) $action;
480 $icons[] = $this->
getUIFactory()->button()->shy(
'', $action)->withSymbol($icon);
490 $this->
txt(
'footer_icons'),
496 $additional_texts = $component->getAdditionalTexts();
497 if ([] !== $additional_texts) {
498 $texts =
array_map(
static fn($text) => [$text,
null], $additional_texts);
503 $this->
txt(
'footer_texts'),
510 return $template->get() . $default_renderer->render($component->getModals());
519 string $section_type,
520 string $section_label,
521 array $section_items = [],
523 foreach ($section_items as [$content, $title]) {
525 if (
null !== $title) {
529 $content = $default_renderer->render($content);
546 string $section_type,
547 string $section_label,
548 array $section_icons = [],
550 foreach ($section_icons as $icon) {
552 $template->
setVariable(
'ICON', $default_renderer->render($icon));
561 string $section_type,
562 string $section_label,
565 $template->
setVariable(
'SECTION_TYPE', $section_type);
566 $template->
setVariable(
'SECTION_LABEL', $section_label);
572 return $component->getPermanentURL() !==
null 573 || !empty($component->getAdditionalLinkGroups())
574 || !empty($component->getAdditionalLinks())
575 || !empty($component->getAdditionalIcons())
576 || !empty($component->getAdditionalTexts());
584 parent::registerResources($registry);
585 $registry->
register(
'assets/js/mainbar.js');
586 $registry->
register(
'assets/js/maincontrols.min.js');
587 $registry->
register(
'assets/js/GS.js');
588 $registry->
register(
'assets/js/system_info.js');
589 $registry->
register(
'assets/js/footer.min.js');
594 $template = $this->
getTemplate(
"tpl.permanent-link.html",
true,
true);
596 $code =
function (
string $id) use ($permanent_url):
string {
598 $perm_url = $this->
jsonEncode((
string) $permanent_url);
600 return "document.getElementById($id).addEventListener('click', e => il.Footer.permalink.copyText($perm_url) 601 .then(() => il.Footer.permalink.showTooltip(e.target.nextElementSibling, 5000)));";
603 $button = $this->
getUIFactory()->button()->shy($this->
txt(
'copy_perma_link'),
'')->withAdditionalOnLoadCode($code);
605 $template->setVariable(
'PERMANENT', $renderer->render($button));
606 $template->setVariable(
'PERMANENT_TOOLTIP', $this->
txt(
'perma_link_copied'));
608 return $template->get();
613 return json_encode($value, JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_THROW_ON_ERROR);
Registry for resources required by rendered output like Javascript or CSS.
permanentLink(string $permanent_url, RendererInterface $renderer)
parseFooterSection(Template $template, string $section_type, string $section_label,)
This describes the MainBar.
const DENOTATION_IMPORTANT
getDisengageAllSignal()
This signal disengages all slates when triggered.
getInitiallyHiddenToolIds()
There are tools that are rendered invisible before first activation.
calculateMainBarTreePosition($pos, $slate)
convertSpecialCharacters(string $value)
renderToolEntry(string $entry_id, string $mb_id, MainBar $component, UITemplateWrapper $tpl, RendererInterface $default_renderer)
const BLOCK_METABAR_ENTRIES
txt(string $id)
Get a text from the language file.
withOnLoadCode(Closure $binder)
setCurrentBlock(string $name)
Set the block to work on.
parseAdditionalFooterSectionIcons(Template $template, RendererInterface $default_renderer, string $section_type, string $section_label, array $section_icons=[],)
setVariable(string $name, $value)
Set a variable in the current block.
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
getEntryClickSignal()
The Signal is triggered when any Entry is being clicked.
const BLOCK_MAINBAR_ENTRIES
getDisengageAllSignal()
This signal disengages all slates when triggered.
getTemplate(string $name, bool $purge_unfilled_vars, bool $purge_unused_blocks)
Get template of component this renderer is made for.
renderSystemInfo(Component\MainControls\SystemInfo $component, RendererInterface $default_renderer)
renderModeInfo(ModeInfo $component, RendererInterface $default_renderer)
parseAdditionalFooterSectionItems(Template $template, RendererInterface $default_renderer, string $section_type, string $section_label, array $section_items=[],)
const DENOTATION_BREAKING
const BLOCK_MAINBAR_TOOLS
withAdditionalEntry(string $id, $entry)
Append an entry.
bindMainbarJS(MainBar $component)
cannotHandleComponent(Component $component)
This method MUST be called by derived component renderers, if.
getToolsButton()
Returns the button of the tools-trigger.
register(string $name)
Add a dependency.
isFooterVisible(I\Footer $component)
parseCurrentBlock()
Parse the block that is currently worked on.
This describes the MetaBar.
renderMainbarEntry(array $entries, string $block, MainBar $component, UITemplateWrapper $tpl, RendererInterface $default_renderer)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
renderTriggerButtonsAndSlates(UITemplateWrapper $tpl, RendererInterface $default_renderer, Signal $entry_signal, string $block, array $entries, ?string $active=null)
getUIFactory()
Get a UI factory.
render(Component\Component $component, RendererInterface $default_renderer)
registerResources(ResourceRegistry $registry)
Announce resources this renderer requires.
getToggleToolsSignal()
Signal to toggle the tools-section.
getEngageToolSignal(string $tool_id)
Signal to engage a tool from outside the MainBar.
renderFooter(I\Footer $component, RendererInterface $default_renderer)
getCloseButtons()
Buttons to close tools; maybe configure with callback.
Base class for all component renderers.
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.