ILIAS  release_8 Revision v8.24
Renderer.php
Go to the documentation of this file.
1<?php
2
3declare(strict_types=1);
4
22
24use ILIAS\UI\Renderer as RendererInterface;
28
30{
34 public function render(Component\Component $component, RendererInterface $default_renderer): string
35 {
36 $this->checkComponent($component);
37
38 if ($component instanceof Component\Button\Close) {
39 return $this->renderClose($component);
40 } elseif ($component instanceof Component\Button\Minimize) {
41 return $this->renderMinimize($component);
42 } elseif ($component instanceof Component\Button\Toggle) {
43 return $this->renderToggle($component);
44 } elseif ($component instanceof Component\Button\Month) {
45 return $this->renderMonth($component);
46 } else {
50 return $this->renderButton($component, $default_renderer);
51 }
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 $label = $component->getLabel();
85 if ($label !== null) {
86 $tpl->setVariable("LABEL", $component->getLabel());
87 }
88 if ($component->isActive()) {
89 // The actions might also be a list of signals, these will be appended by
90 // bindJavascript in maybeRenderId.
91 if (is_string($action) && $action != "") {
92 $component = $component->withAdditionalOnLoadCode(function ($id) use ($action) {
93 $action = str_replace("&amp;", "&", $action);
94
95 return "$('#$id').on('click', function(event) {
96 window.location = '$action';
97 return false;
98 });";
99 });
100 }
101
102 if ($component instanceof Component\Button\LoadingAnimationOnClick && $component->hasLoadingAnimationOnClick()) {
103 $component = $component->withAdditionalOnLoadCode(fn ($id) => "$('#$id').click(function(e) { il.UI.button.activateLoadingAnimation('$id')});");
104 }
105 } else {
106 $tpl->touchBlock("disabled");
107 }
108 $aria_label = $component->getAriaLabel();
109 if ($aria_label != null) {
110 $tpl->setCurrentBlock("with_aria_label");
111 $tpl->setVariable("ARIA_LABEL", $aria_label);
112 $tpl->parseCurrentBlock();
113 }
114
115 if ($component instanceof Component\Button\Engageable
116 && $component->isEngageable()
117 ) {
118 if ($component->isEngaged()) {
119 $tpl->touchBlock("engaged");
120 $aria_pressed = 'true';
121 } else {
122 $aria_pressed = 'false';
123 }
124
125 //Note that Bulky Buttons need to handle aria_pressed seperatly due to possible aria_role conflicts
126 if (!($component instanceof Bulky)) {
127 $tpl->setCurrentBlock("with_aria_pressed");
128 $tpl->setVariable("ARIA_PRESSED", $aria_pressed);
129 $tpl->parseCurrentBlock();
130 }
131 }
132
133 $this->maybeRenderId($component, $tpl);
134
135 if ($component instanceof Component\Button\Tag) {
136 $this->additionalRenderTag($component, $tpl);
137 }
138
139 if ($component instanceof Component\Button\Bulky) {
140 $this->additionalRenderBulky($component, $default_renderer, $tpl);
141 }
142
143 return $tpl->get();
144 }
145
149 public function registerResources(ResourceRegistry $registry): void
150 {
151 parent::registerResources($registry);
152 $registry->register('./src/UI/templates/js/Button/button.js');
153 $registry->register("./node_modules/moment/min/moment-with-locales.min.js");
154 $registry->register("./node_modules/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js");
155 }
156
157 protected function renderClose(Component\Button\Close $component): string
158 {
159 $tpl = $this->getTemplate("tpl.close.html", true, true);
160 // This is required as the rendering seems to only create any output at all
161 // if any var was set or block was touched.
162 $tpl->setVariable("FORCE_RENDERING", "");
163 $tpl->setVariable("ARIA_LABEL", $this->txt("close"));
164 $this->maybeRenderId($component, $tpl);
165 return $tpl->get();
166 }
167
168 protected function renderMinimize(Component\Button\Minimize $component): string
169 {
170 $tpl = $this->getTemplate("tpl.minimize.html", true, true);
171 $tpl->setVariable("ARIA_LABEL", $this->txt("minimize"));
172 $this->maybeRenderId($component, $tpl);
173 return $tpl->get();
174 }
175
176 protected function renderToggle(Component\Button\Toggle $component): string
177 {
178 $tpl = $this->getTemplate("tpl.toggle.html", true, true);
179
180 $on_action = $component->getActionOn();
181 $off_action = $component->getActionOff();
182
183 $on_url = (is_string($on_action))
184 ? $on_action
185 : "";
186
187 $off_url = (is_string($off_action))
188 ? $off_action
189 : "";
190
191 $signals = [];
192
193 foreach ($component->getTriggeredSignals() as $s) {
194 $signals[] = [
195 "signal_id" => $s->getSignal()->getId(),
196 "event" => $s->getEvent(),
197 "options" => $s->getSignal()->getOptions()
198 ];
199 }
200
201 $signals = json_encode($signals);
202
203 $button_status = 'off';
204 if ($component->isEngaged()) {
205 $button_status = 'on';
206 }
207
208 if ($component->isActive()) {
209 $component = $component->withAdditionalOnLoadCode(fn ($id) => "$('#$id').on('click', function(event) {
210 il.UI.button.handleToggleClick(event, '$id', '$on_url', '$off_url', $signals);
211 return false; // stop event propagation
212 });");
213 $tpl->setCurrentBlock("with_on_off_label");
214 $tpl->setVariable("ON_LABEL", $this->txt("toggle_on"));
215 $tpl->setVariable("OFF_LABEL", $this->txt("toggle_off"));
216 $tpl->parseCurrentBlock();
217 } else {
218 $tpl->touchBlock("disabled");
219 $button_status = 'unavailable';
220 }
221
222 $tpl->touchBlock($button_status);
223
224 $label = $component->getLabel();
225 if (!empty($label)) {
226 $tpl->setCurrentBlock("with_label");
227 $tpl->setVariable("LABEL", $label);
228 $tpl->parseCurrentBlock();
229 }
230 $aria_label = $component->getAriaLabel();
231 if ($aria_label != null) {
232 $tpl->setCurrentBlock("with_aria_label");
233 $tpl->setVariable("ARIA_LABEL", $aria_label);
234 $tpl->parseCurrentBlock();
235 }
236 $this->maybeRenderId($component, $tpl);
237 return $tpl->get();
238 }
239
240 protected function maybeRenderId(Component\JavaScriptBindable $component, Template $tpl): void
241 {
242 $id = $this->bindJavaScript($component);
243 if ($id !== null) {
244 $tpl->setCurrentBlock("with_id");
245 $tpl->setVariable("ID", $id);
246 $tpl->parseCurrentBlock();
247 }
248 }
249
250 protected function renderMonth(Component\Button\Month $component): string
251 {
252 $def = $component->getDefault();
253
254 for ($i = 1; $i <= 12; $i++) {
255 $this->toJS(array("month_" . str_pad((string) $i, 2, "0", STR_PAD_LEFT) . "_short"));
256 }
257
258 $tpl = $this->getTemplate("tpl.month.html", true, true);
259
260 $month = explode("-", $def);
261 $tpl->setVariable("DEFAULT_LABEL", $this->txt("month_" . str_pad($month[0], 2, "0", STR_PAD_LEFT) . "_short") . " " . $month[1]);
262 $tpl->setVariable("DEF_DATE", $month[0] . "/1/" . $month[1]);
263 // see https://github.com/moment/moment/tree/develop/locale
264 $lang_key = in_array($this->getLangKey(), array("ar", "bg", "cs", "da", "de", "el", "en", "es", "et", "fa", "fr", "hu", "it",
265 "ja", "ka", "lt", "nl", "pl", "pt", "ro", "ru", "sk", "sq", "sr", "tr", "uk", "vi", "zh"))
266 ? $this->getLangKey()
267 : "en";
268 if ($lang_key == "zh") {
269 $lang_key = "zh-cn";
270 }
271 $tpl->setVariable("LANG", $lang_key);
272
273 $component = $component->withAdditionalOnLoadCode(fn ($id) => "il.UI.button.initMonth('$id');");
274 $id = $this->bindJavaScript($component);
275
276 $tpl->setVariable("ID", $id);
277
278 return $tpl->get();
279 }
280
281 protected function additionalRenderTag(Component\Button\Tag $component, Template $tpl): void
282 {
283 $tpl->touchBlock('rel_' . $component->getRelevance());
284
285 $classes = trim(join(' ', $component->getClasses()));
286 if ($classes !== '') {
287 $tpl->setVariable("CLASSES", $classes);
288 }
289
290 $bgcol = $component->getBackgroundColor();
291 if ($bgcol) {
292 $tpl->setVariable("BGCOL", $bgcol->asHex());
293 }
294 $forecol = $component->getForegroundColor();
295 if ($forecol) {
296 $tpl->setVariable("FORECOL", $forecol->asHex());
297 }
298 }
299
300 protected function additionalRenderBulky(
301 Component\Button\Button $component,
302 RendererInterface $default_renderer,
304 ): void {
305 $renderer = $default_renderer->withAdditionalContext($component);
306 $tpl->setVariable("ICON_OR_GLYPH", $renderer->render($component->getIconOrGlyph()));
307 $label = $component->getLabel();
308 if ($label !== null) {
309 $tpl->setVariable("LABEL", $label);
310 }
311
312 $aria_role = $component->getAriaRole();
313 if ($aria_role != null) {
314 $tpl->setCurrentBlock("with_aria_role");
315 $tpl->setVariable("ARIA_ROLE", $aria_role);
316 $tpl->parseCurrentBlock();
317 }
318 if ($component->isEngageable()) {
319 if ($aria_role == Bulky::MENUITEM) {
320 $tpl->touchBlock("with_aria_haspopup");
321 } else {
322 //Note that aria-role='menuitems MUST-NOT have Aria-pressed to true;
323 $tpl->setCurrentBlock("with_aria_pressed");
324 if ($component->isEngaged()) {
325 $tpl->setVariable("ARIA_PRESSED", "true");
326 } else {
327 $tpl->setVariable("ARIA_PRESSED", "false");
328 }
329 $tpl->parseCurrentBlock();
330 }
331 }
332 }
333
337 protected function getComponentInterfaceName(): array
338 {
339 return array(Component\Button\Primary::class
340 , Component\Button\Standard::class
341 , Component\Button\Close::class
342 , Component\Button\Minimize::class
343 , Component\Button\Shy::class
344 , Component\Button\Month::class
345 , Component\Button\Tag::class
346 , Component\Button\Bulky::class
347 , Component\Button\Toggle::class
348 );
349 }
350}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
additionalRenderBulky(Component\Button\Button $component, RendererInterface $default_renderer, Template $tpl)
Definition: Renderer.php:300
renderToggle(Component\Button\Toggle $component)
Definition: Renderer.php:176
additionalRenderTag(Component\Button\Tag $component, Template $tpl)
Definition: Renderer.php:281
renderClose(Component\Button\Close $component)
Definition: Renderer.php:157
maybeRenderId(Component\JavaScriptBindable $component, Template $tpl)
Definition: Renderer.php:240
registerResources(ResourceRegistry $registry)
Announce resources this renderer requires.
Definition: Renderer.php:149
renderMonth(Component\Button\Month $component)
Definition: Renderer.php:250
renderButton(Component\Button\Button $component, RendererInterface $default_renderer)
Definition: Renderer.php:54
getComponentInterfaceName()
Get the name of the component-interface this renderer is supposed to render.ATTENTION: Fully qualifie...
Definition: Renderer.php:337
renderMinimize(Component\Button\Minimize $component)
Definition: Renderer.php:168
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.
checkComponent(Component $component)
Check if a given component fits this renderer and throw \LogicError if that is not the case.
toJS($key)
Add language var to client side (il.Language)
getTemplate(string $name, bool $purge_unfilled_vars, bool $purge_unused_blocks)
Get template of component this renderer is made for.
Interface to be extended by components that have the possibility to bind to Javascript.
render(Component $component, Renderer $default_renderer)
Render the component if possible and delegate additional rendering to the default_renderer.
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
An entity that renders components to a string output.
Definition: Renderer.php:31
if($DIC->http() ->request() ->getMethod()=="GET" &&isset($DIC->http() ->request() ->getQueryParams()['tex'])) $tpl
Definition: latex.php:41
$i
Definition: metadata.php:41
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...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: Bulky.php:21
trait LoadingAnimationOnClick
Implements LoadingAnimationOnClick interface.