ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
Renderer.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
25use ILIAS\UI\Renderer as RendererInterface;
32
34{
38 public function render(Component\Component $component, RendererInterface $default_renderer): string
39 {
40 if ($component instanceof Component\Button\Close) {
41 return $this->renderClose($component);
42 } elseif ($component instanceof Component\Button\Minimize) {
43 return $this->renderMinimize($component);
44 } elseif ($component instanceof Component\Button\Toggle) {
45 return $this->renderToggle($component);
46 } elseif ($component instanceof Component\Button\Month) {
47 return $this->renderMonth($component);
48 } elseif ($component instanceof Component\Button\Button) {
49 return $this->renderButton($component, $default_renderer);
50 }
51 $this->cannotHandleComponent($component);
52 }
53
54 protected function renderButton(Component\Button\Button $component, RendererInterface $default_renderer): string
55 {
56 $tpl_name = "";
57 if ($component instanceof Component\Button\Primary) {
58 $tpl_name = "tpl.primary.html";
59 }
60 if ($component instanceof Component\Button\Standard) {
61 $tpl_name = "tpl.standard.html";
62 }
63 if ($component instanceof Component\Button\Shy) {
64 $tpl_name = "tpl.shy.html";
65 }
66 if ($component instanceof Component\Button\Tag) {
67 $tpl_name = "tpl.tag.html";
68 }
69 if ($component instanceof Component\Button\Bulky) {
70 $tpl_name = "tpl.bulky.html";
71 }
72
73 $tpl = $this->getTemplate($tpl_name, true, true);
74
75 $action = $component->getAction();
76 // The action is always put in the data-action attribute to have it available
77 // on the client side, even if it is not available on rendering.
78 if (is_string($action)) {
79 $tpl->setCurrentBlock("with_data_action");
80 $tpl->setVariable("ACTION", $action);
81 $tpl->parseCurrentBlock();
82 }
83
84 $tpl->setVariable("LABEL", $component->getLabel());
85 $symbol = $component->getSymbol();
86 if ($symbol !== null) {
87 if ($component->getLabel() !== '') {
88 $symbol = $symbol->withLabel('');
89 }
90 $tpl->setVariable("SYMBOL", $default_renderer->render($symbol));
91 }
92
93 if ($component->isActive()) {
94 // The actions might also be a list of signals, these will be appended by
95 // bindJavascript in maybeRenderId.
96 if (is_string($action) && $action != "") {
97 $component = $component->withAdditionalOnLoadCode(function ($id) use ($action) {
98 $action = str_replace("&amp;", "&", $action);
99
100 return "$('#$id').on('click', function(event) {
101 window.location = '$action';
102 return false;
103 });";
104 });
105 }
106
107 if ($component instanceof Component\Button\LoadingAnimationOnClick && $component->hasLoadingAnimationOnClick()) {
108 $component = $component->withAdditionalOnLoadCode(fn($id) => "$('#$id').click(function(e) { il.UI.button.activateLoadingAnimation('$id')});");
109 }
110 } else {
111 $tpl->touchBlock("disabled");
112 }
113 $aria_label = $component->getAriaLabel();
114 if ($aria_label != null) {
115 $tpl->setCurrentBlock("with_aria_label");
116 $tpl->setVariable("ARIA_LABEL", $aria_label);
117 $tpl->parseCurrentBlock();
118 }
119
120 if ($component instanceof Component\Button\Engageable
121 && $component->isEngageable()
122 ) {
123 if ($component->isEngaged()) {
124 $tpl->touchBlock("engaged");
125 $aria_pressed = 'true';
126 } else {
127 $aria_pressed = 'false';
128 }
129
130 //Note that Bulky Buttons need to handle aria_pressed seperatly due to possible aria_role conflicts
131 if (!($component instanceof Bulky)) {
132 $tpl->setCurrentBlock("with_aria_pressed");
133 $tpl->setVariable("ARIA_PRESSED", $aria_pressed);
134 $tpl->parseCurrentBlock();
135 }
136 }
137
138 $tooltip_embedding = $this->getTooltipRenderer()->maybeGetTooltipEmbedding(...$component->getHelpTopics());
139 if ($tooltip_embedding) {
140 $component = $component->withAdditionalOnLoadCode($tooltip_embedding[1]);
141 }
142
143 $this->maybeRenderId($component, $tpl);
144
145 if ($component instanceof Component\Button\Tag) {
146 $this->additionalRenderTag($component, $tpl);
147 }
148
149 if ($component instanceof Component\Button\Bulky) {
150 $this->additionalRenderBulky($component, $default_renderer, $tpl);
151 }
152
153 if (!$tooltip_embedding) {
154 return $tpl->get();
155 }
156
157 $tooltip_id = $this->createId();
158 $tpl->setCurrentBlock("with_aria_describedby");
159 $tpl->setVariable("ARIA_DESCRIBED_BY", $tooltip_id);
160 $tpl->parseCurrentBlock();
161
162 return $tooltip_embedding[0]($tooltip_id, $tpl->get());
163 }
164
168 public function registerResources(ResourceRegistry $registry): void
169 {
170 parent::registerResources($registry);
171 $registry->register('assets/js/button.js');
172 $registry->register("./assets/js/moment-with-locales.min.js");
173 }
174
175 protected function renderClose(Component\Button\Close $component): string
176 {
177 $tpl = $this->getTemplate("tpl.close.html", true, true);
178 // This is required as the rendering seems to only create any output at all
179 // if any var was set or block was touched.
180 $tpl->setVariable("FORCE_RENDERING", "");
181 $tpl->setVariable("ARIA_LABEL", $this->txt("close"));
182 $this->maybeRenderId($component, $tpl);
183 return $tpl->get();
184 }
185
186 protected function renderMinimize(Component\Button\Minimize $component): string
187 {
188 $tpl = $this->getTemplate("tpl.minimize.html", true, true);
189 $tpl->setVariable("ARIA_LABEL", $this->txt("minimize"));
190 $this->maybeRenderId($component, $tpl);
191 return $tpl->get();
192 }
193
194 protected function renderToggle(Component\Button\Toggle $component): string
195 {
196 $tpl = $this->getTemplate("tpl.toggle.html", true, true);
197
198 $on_action = $component->getActionOn();
199 $off_action = $component->getActionOff();
200
201 $on_url = (is_string($on_action))
202 ? $on_action
203 : "";
204
205 $off_url = (is_string($off_action))
206 ? $off_action
207 : "";
208
209 $signals = [];
210
211 foreach ($component->getTriggeredSignals() as $s) {
212 $signals[] = [
213 "signal_id" => $s->getSignal()->getId(),
214 "event" => $s->getEvent(),
215 "options" => $s->getSignal()->getOptions()
216 ];
217 }
218
219 $signals = json_encode($signals);
220
221 $button_status = 'off';
222 if ($component->isEngaged()) {
223 $button_status = 'on';
224 }
225
226 if ($component->isActive()) {
227 $component = $component->withAdditionalOnLoadCode(
228 fn($id) =>
229 "$('#$id').on('click', function(event) {
230 il.UI.button.handleToggleClick(event, '$id', '$on_url', '$off_url', $signals);
231 return false; // stop event propagation
232 });"
233 );
234 $tpl->setCurrentBlock("with_on_off_label");
235 $tpl->setVariable("ON_LABEL", $this->txt("toggle_on"));
236 $tpl->setVariable("OFF_LABEL", $this->txt("toggle_off"));
237 $tpl->parseCurrentBlock();
238 } else {
239 $tpl->touchBlock("disabled");
240 $button_status = 'unavailable';
241 }
242
243 $tpl->touchBlock($button_status);
244
245 $label = $component->getLabel();
246 if (!empty($label)) {
247 $tpl->setCurrentBlock("with_label");
248 $tpl->setVariable("LABEL", $label);
249 $tpl->parseCurrentBlock();
250 }
251 $aria_label = $component->getAriaLabel();
252 if ($aria_label != null) {
253 $tpl->setCurrentBlock("with_aria_label");
254 $tpl->setVariable("ARIA_LABEL", $aria_label);
255 $tpl->parseCurrentBlock();
256 }
257
258 $tooltip_embedding = $this->getTooltipRenderer()->maybeGetTooltipEmbedding(...$component->getHelpTopics());
259 if ($tooltip_embedding) {
260 $component = $component->withAdditionalOnLoadCode($tooltip_embedding[1]);
261 $tooltip_id = $this->createId();
262 $tpl->setCurrentBlock("with_aria_describedby");
263 $tpl->setVariable("ARIA_DESCRIBED_BY", $tooltip_id);
264 $tpl->parseCurrentBlock();
265
266 $this->maybeRenderId($component, $tpl);
267 return $tooltip_embedding[0]($tooltip_id, $tpl->get());
268 }
269
270 $this->maybeRenderId($component, $tpl);
271 return $tpl->get();
272 }
273
274 protected function maybeRenderId(Component\JavaScriptBindable $component, Template $tpl): void
275 {
276 $id = $this->bindJavaScript($component);
277 if ($id !== null) {
278 $tpl->setCurrentBlock("with_id");
279 $tpl->setVariable("ID", $id);
280 $tpl->parseCurrentBlock();
281 }
282 }
283
284 protected function renderMonth(Component\Button\Month $component): string
285 {
286 $tpl = $this->getTemplate("tpl.month.html", true, true);
287
288 $component = $component->withAdditionalOnLoadCode(fn($id) => "il.UI.button.initMonth('$id');");
289 $id = $this->bindJavaScript($component);
290 $tpl->setVariable("ID", $id);
291
292 $def = $component->getDefault();
293 $value = implode('-', array_reverse(explode("-", $def)));
294 $tpl->setVariable("DEFAULT", $value);
295
296 return $tpl->get();
297 }
298
299 protected function additionalRenderTag(Component\Button\Tag $component, Template $tpl): void
300 {
301 $tpl->touchBlock('rel_' . $component->getRelevance());
302
303 $classes = trim(join(' ', $component->getClasses()));
304 if ($classes !== '') {
305 $tpl->setVariable("CLASSES", $classes);
306 }
307
308 $bgcol = $component->getBackgroundColor();
309 if ($bgcol) {
310 $tpl->setVariable("BGCOL", $bgcol->asHex());
311 }
312 $forecol = $component->getForegroundColor();
313 if ($forecol) {
314 $tpl->setVariable("FORECOL", $forecol->asHex());
315 }
316 }
317
318 protected function additionalRenderBulky(
319 Component\Button\Button $component,
320 RendererInterface $default_renderer,
321 Template $tpl
322 ): void {
323 $aria_role = $component->getAriaRole();
324 if ($aria_role != null) {
325 $tpl->setCurrentBlock("with_aria_role");
326 $tpl->setVariable("ARIA_ROLE", $aria_role);
327 $tpl->parseCurrentBlock();
328 }
329 if ($component->isEngageable()) {
330 if ($aria_role == Bulky::MENUITEM) {
331 $tpl->touchBlock("with_aria_haspopup");
332 } else {
333 //Note that aria-role='menuitems MUST-NOT have Aria-pressed to true;
334 $tpl->setCurrentBlock("with_aria_pressed");
335 if ($component->isEngaged()) {
336 $tpl->setVariable("ARIA_PRESSED", "true");
337 } else {
338 $tpl->setVariable("ARIA_PRESSED", "false");
339 }
340 $tpl->parseCurrentBlock();
341 }
342 }
343 }
344}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
additionalRenderBulky(Component\Button\Button $component, RendererInterface $default_renderer, Template $tpl)
Definition: Renderer.php:318
renderToggle(Component\Button\Toggle $component)
Definition: Renderer.php:194
render(Component\Component $component, RendererInterface $default_renderer)
Definition: Renderer.php:38
additionalRenderTag(Component\Button\Tag $component, Template $tpl)
Definition: Renderer.php:299
renderClose(Component\Button\Close $component)
Definition: Renderer.php:175
maybeRenderId(Component\JavaScriptBindable $component, Template $tpl)
Definition: Renderer.php:274
registerResources(ResourceRegistry $registry)
Announce resources this renderer requires.
Definition: Renderer.php:168
renderMonth(Component\Button\Month $component)
Definition: Renderer.php:284
renderButton(Component\Button\Button $component, RendererInterface $default_renderer)
Definition: Renderer.php:54
renderMinimize(Component\Button\Minimize $component)
Definition: Renderer.php:186
cannotHandleComponent(Component $component)
This method MUST be called by derived component renderers, if.
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.
getTemplate(string $name, bool $purge_unfilled_vars, bool $purge_unused_blocks)
Get template of component this renderer is made for.
This class is supposed to unify rendering of tooltips over all components and should also be usable b...
Engageable Components have an "engaged" state and will be displayed accordingly.
Definition: Engageable.php:29
isEngageable()
Returns whether the button is stateful or not.
Interface for buttons with loading animation on click.
hasLoadingAnimationOnClick()
Return whether loading animation has been activated.
Interface to be extended by components that have the possibility to bind to Javascript.
This describes how an icon could be modified during construction of UI.
Definition: Icon.php:29
This describes a symbol.
Definition: Symbol.php:30
Registry for resources required by rendered output like Javascript or CSS.
register(string $name)
Add a dependency.
Interface to templating as it is used in the UI framework.
Definition: Template.php:29
setVariable(string $name, $value)
Set a variable in the current block.
setCurrentBlock(string $name)
Set the block to work on.
touchBlock(string $name)
Touch a block without working further on it.
parseCurrentBlock()
Parse the block that is currently worked on.
An entity that renders components to a string output.
Definition: Renderer.php:31
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: Bulky.php:21
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: Bulky.php:21