ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
Renderer.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 2017 Jesús López <lopez@leifos.de> Extended GPL, see docs/LICENSE */
3 
5 
10 
16 {
17  public const MODE_ROLE = "group";
18 
23  public function render(Component\Component $component, RendererInterface $default_renderer)
24  {
25  $this->checkComponent($component);
26 
27  if ($component instanceof Component\ViewControl\Mode) {
28  return $this->renderMode($component, $default_renderer);
29  }
30  if ($component instanceof Component\ViewControl\Section) {
31  return $this->renderSection($component, $default_renderer);
32  }
33  if ($component instanceof Component\ViewControl\Sortation) {
34  return $this->renderSortation($component, $default_renderer);
35  }
36  if ($component instanceof Component\ViewControl\Pagination) {
37  return $this->renderPagination($component, $default_renderer);
38  }
39  }
40 
41  protected function renderMode(Component\ViewControl\Mode $component, RendererInterface $default_renderer)
42  {
43  $f = $this->getUIFactory();
44 
45  $tpl = $this->getTemplate("tpl.mode.html", true, true);
46 
47  $active = $component->getActive();
48  if ($active == "") {
49  $activate_first_item = true;
50  }
51 
52  foreach ($component->getLabelledActions() as $label => $action) {
53  $tpl->setVariable("ARIA", $this->txt($component->getAriaLabel()));
54  $tpl->setVariable("ROLE", self::MODE_ROLE);
55 
56  $tpl->setCurrentBlock("view_control");
57 
58  //At this point we don't have an specific text for the button aria label. component->getAriaLabel gets the main viewcontrol aria label.
59  $button = $f->button()->standard($label, $action)->withAriaLabel($label);
60  if ($activate_first_item) {
61  $button = $button->withEngagedState(true);
62  $activate_first_item = false;
63  } elseif ($active == $label) {
64  $button = $button->withEngagedState(true);
65  } else {
66  $button = $button->withEngagedState(false);
67  }
68  $tpl->setVariable("BUTTON", $default_renderer->render($button));
69  $tpl->parseCurrentBlock();
70  }
71 
72  return $tpl->get();
73  }
74 
75  protected function renderSection(Component\ViewControl\Section $component, RendererInterface $default_renderer)
76  {
77  $tpl = $this->getTemplate("tpl.section.html", true, true);
78 
79  // render middle button
80  $tpl->setVariable("BUTTON", $default_renderer->render($component->getSelectorButton()));
81 
82  // previous button
83  $this->renderSectionButton($component->getPreviousActions(), $tpl, "prev");
84 
85  // next button
86  $this->renderSectionButton($component->getNextActions(), $tpl, "next");
87 
88  return $tpl->get();
89  }
90 
96  protected function renderSectionButton(Component\Button\Button $component, $tpl, $type)
97  {
98  $uptype = strtoupper($type);
99 
100  $action = $component->getAction();
101  $tpl->setVariable($uptype . "_ACTION", $action);
102  $label = ($type == "next")
103  ? $this->txt("next")
104  : $this->txt("previous");
105  $tpl->setVariable($uptype . "_LABEL", $label);
106  if ($component->isActive()) {
107  $tpl->setCurrentBlock($type . "_with_href");
108  $tpl->setVariable($uptype . "_HREF", $action);
109  $tpl->parseCurrentBlock();
110  } else {
111  $tpl->touchBlock($type . "_disabled");
112  }
113  $this->renderId($component, $tpl, $type . "_with_id", $uptype . "_ID");
114  }
115 
116 
117  protected function renderSortation(Component\ViewControl\Sortation $component, RendererInterface $default_renderer)
118  {
119  $f = $this->getUIFactory();
120 
121  $tpl = $this->getTemplate("tpl.sortation.html", true, true);
122 
123  $component = $component->withResetSignals();
124  $triggeredSignals = $component->getTriggeredSignals();
125  if ($triggeredSignals) {
126  $internal_signal = $component->getSelectSignal();
127  $signal = $triggeredSignals[0]->getSignal();
128 
129  $component = $component->withAdditionalOnLoadCode(function ($id) use ($internal_signal, $signal) {
130  return "$(document).on('{$internal_signal}', function(event, signalData) {
131  il.UI.viewcontrol.sortation.onInternalSelect(event, signalData, '{$signal}', '{$id}');
132  return false;
133  })";
134  });
135  }
136 
137  $this->renderId($component, $tpl, "id", "ID");
138 
139  //setup entries
140  $options = $component->getOptions();
141  $init_label = $component->getLabel();
142  $items = array();
143  foreach ($options as $val => $label) {
144  if ($triggeredSignals) {
145  $shy = $f->button()->shy($label, $val)->withOnClick($internal_signal);
146  } else {
147  $url = $component->getTargetURL();
148  $url .= (strpos($url, '?') === false) ? '?' : '&';
149  $url .= $component->getParameterName() . '=' . $val;
150  $shy = $f->button()->shy($label, $url);
151  }
152  $items[] = $shy;
153  }
154 
155  $dd = $f->dropdown()->standard($items)
156  ->withLabel($init_label);
157 
158  $tpl->setVariable('SORTATION_DROPDOWN', $default_renderer->render($dd));
159  return $tpl->get();
160  }
161 
162 
163 
164  protected function renderPagination(Component\ViewControl\Pagination $component, RendererInterface $default_renderer)
165  {
166  $tpl = $this->getTemplate("tpl.pagination.html", true, true);
167 
171  $component = $component->withResetSignals();
172  $triggeredSignals = $component->getTriggeredSignals();
173  if ($triggeredSignals) {
174  $internal_signal = $component->getInternalSignal();
175  $signal = $triggeredSignals[0]->getSignal();
176  $component = $component->withOnLoadCode(function ($id) use ($internal_signal, $signal) {
177  return "$(document).on('{$internal_signal}', function(event, signalData) {
178  il.UI.viewcontrol.pagination.onInternalSelect(event, signalData, '{$signal}', '{$id}');
179  return false;
180  })";
181  });
182 
183  $id = $this->bindJavaScript($component);
184  $tpl->setVariable('ID', $id);
185  }
186 
187  $range = $this->getPaginationRange($component);
188  $chunk_options = array();
189  foreach ($range as $entry) {
190  $shy = $this->getPaginationShyButton($entry, $component);
191  if ((int) $entry === $component->getCurrentPage()) {
192  $shy = $shy->withEngagedState(true);
193  }
194  $chunk_options[] = $shy;
195  }
196 
197  if ($component->getDropdownAt() == null ||
198  $component->getDropdownAt() > $component->getNumberOfPages()) {
199  foreach ($chunk_options as $entry) {
200  $tpl->setCurrentBlock("entry");
201  $tpl->setVariable('BUTTON', $default_renderer->render($entry));
202  $tpl->parseCurrentBlock();
203  }
204  } else {
205  //if threshold is reached, render as dropdown
206  $f = $this->getUIFactory();
207 
208  $dd_label_template = $component->getDropdownLabel();
209  if ($dd_label_template === $component->getDefaultDropdownLabel()) {
210  $dd_label_template = $this->txt($dd_label_template);
211  }
212  $dd_label = sprintf(
213  $dd_label_template,
214  $component->getCurrentPage() + 1,
215  $component->getNumberOfPages()
216  );
217 
218  $dd = $f->dropdown()->standard($chunk_options)->withLabel($dd_label);
219  $tpl->setCurrentBlock("entry");
220  $tpl->setVariable('BUTTON', $default_renderer->render($dd));
221  $tpl->parseCurrentBlock();
222  }
223 
224  if ($component->getMaxPaginationButtons()) {
225  $this->setPaginationFirstLast($component, $range, $default_renderer, $tpl);
226  }
227 
228  $this->setPaginationBrowseControls($component, $default_renderer, $tpl);
229  return $tpl->get();
230  }
231 
239  protected function getPaginationRange(Component\ViewControl\Pagination $component)
240  {
241  if (!$component->getMaxPaginationButtons()) {
242  $start = 0;
243  $stop = max($component->getNumberOfPages() - 1, 0);
244  } else {
245  //current page should be in the middle, so start is half the amount of max entries:
246  $start = (int) ($component->getCurrentPage() - floor($component->getMaxPaginationButtons() / 2));
247  $start = max($start, 0); //0, if negative
248  //stop is (calculated) start plus number of entries:
249  $stop = $start + $component->getMaxPaginationButtons() - 1;
250  //if stop exceeds max pages, recalculate both:
251  if ($stop > $component->getNumberOfPages() - 1) {
252  $stop = max($component->getNumberOfPages() - 1, 0); //0, if negative
253  $start = $stop - $component->getMaxPaginationButtons();
254  $start = max($start, 0); //0, if negative
255  }
256  }
257  return range($start, $stop);
258  }
259 
260 
268  protected function getPaginationShyButton($val, Component\ViewControl\Pagination $component, $label = '')
269  {
270  $f = $this->getUIFactory();
271 
272  if ($label === '') {
273  $label = (string) ((int) $val + 1);
274  }
275 
276  if ($component->getTriggeredSignals()) {
277  $shy = $f->button()->shy($label, (string) $val)->withOnClick($component->getInternalSignal());
278  } else {
279  $url = $component->getTargetURL();
280  if (strpos($url, '?') === false) {
281  $url .= '?' . $component->getParameterName() . '=' . $val;
282  } else {
283  $base = substr($url, 0, strpos($url, '?') + 1);
284  $query = parse_url($url, PHP_URL_QUERY);
285  parse_str($query, $params);
286  $params[$component->getParameterName()] = $val;
287  $url = $base . http_build_query($params);
288  }
289  $shy = $f->button()->shy($label, $url);
290  }
291  return $shy;
292  }
293 
303  protected function setPaginationBrowseControls(Component\ViewControl\Pagination $component, RendererInterface $default_renderer, $tpl)
304  {
305  $prev = max(0, $component->getCurrentPage() - 1);
306  $next = $component->getCurrentPage() + 1;
307 
308  $f = $this->getUIFactory();
309 
310  if ($component->getTriggeredSignals()) {
311  $back = $f->symbol()->glyph()->back('')->withOnClick($component->getInternalSignal());
312  $forward = $f->symbol()->glyph()->next('')->withOnClick($component->getInternalSignal());
313  } else {
314  $url = $component->getTargetURL();
315  if (strpos($url, '?') === false) {
316  $url_prev = $url . '?' . $component->getParameterName() . '=' . $prev;
317  $url_next = $url . '?' . $component->getParameterName() . '=' . $next;
318  } else {
319  $base = substr($url, 0, strpos($url, '?') + 1);
320  $query = parse_url($url, PHP_URL_QUERY);
321  parse_str($query, $params);
322 
323  $params[$component->getParameterName()] = $prev;
324  $url_prev = $base . http_build_query($params);
325  $params[$component->getParameterName()] = $next;
326  $url_next = $base . http_build_query($params);
327  }
328 
329  $back = $f->symbol()->glyph()->back($url_prev);
330  $forward = $f->symbol()->glyph()->next($url_next);
331  }
332 
333  if ($component->getCurrentPage() === 0) {
334  $back = $back->withUnavailableAction();
335  }
336  if ($component->getCurrentPage() >= $component->getNumberOfPages() - 1) {
337  $forward = $forward->withUnavailableAction();
338  }
339 
340  $tpl->setVariable('PREVIOUS', $default_renderer->render($back));
341  $tpl->setVariable('NEXT', $default_renderer->render($forward));
342  }
343 
354  protected function setPaginationFirstLast(Component\ViewControl\Pagination $component, $range, RendererInterface $default_renderer, $tpl)
355  {
356  if (!in_array(0, $range)) {
357  $shy = $this->getPaginationShyButton(0, $component);
358  $tpl->setVariable('FIRST', $default_renderer->render($shy));
359  }
360  $last = max($component->getNumberOfPages() - 1, 0);
361  if (!in_array($last, $range)) {
362  $shy = $this->getPaginationShyButton($component->getNumberOfPages() - 1, $component);
363  $tpl->setVariable('LAST', $default_renderer->render($shy));
364  }
365  }
366 
367 
371  public function registerResources(\ILIAS\UI\Implementation\Render\ResourceRegistry $registry)
372  {
373  parent::registerResources($registry);
374  $registry->register('./src/UI/templates/js/ViewControl/sortation.js');
375  $registry->register('./src/UI/templates/js/ViewControl/pagination.js');
376  }
377 
378 
379  protected function renderId(Component\JavaScriptBindable $component, $tpl, $block, $template_var)
380  {
381  $id = $this->bindJavaScript($component);
382  if (!$id) {
383  $id = $this->createId();
384  }
385  $tpl->setCurrentBlock($block);
386  $tpl->setVariable($template_var, $id);
387  $tpl->parseCurrentBlock();
388  }
389 
393  protected function getComponentInterfaceName()
394  {
395  return array(
396  Component\ViewControl\Mode::class,
397  Component\ViewControl\Section::class,
398  Component\ViewControl\Sortation::class,
399  Component\ViewControl\Pagination::class
400  );
401  }
402 }
renderSection(Component\ViewControl\Section $component, RendererInterface $default_renderer)
Definition: Renderer.php:75
setPaginationBrowseControls(Component\ViewControl\Pagination $component, RendererInterface $default_renderer, $tpl)
Add back/next-glyphs to the template for left/right browsing in pagination.
Definition: Renderer.php:303
setPaginationFirstLast(Component\ViewControl\Pagination $component, $range, RendererInterface $default_renderer, $tpl)
Add quick-access to first/last pages in pagination.
Definition: Renderer.php:354
renderSortation(Component\ViewControl\Sortation $component, RendererInterface $default_renderer)
Definition: Renderer.php:117
Class Factory.
checkComponent(Component $component)
Check if a given component fits this renderer and throw if that is not the case. ...
$type
renderId(Component\JavaScriptBindable $component, $tpl, $block, $template_var)
Definition: Renderer.php:379
Class ChatMainBarProvider .
trait JavaScriptBindable
Trait for components implementing JavaScriptBindable providing standard implementation.
render(Component\Component $component, RendererInterface $default_renderer)
Definition: Renderer.php:23
getPaginationShyButton($val, Component\ViewControl\Pagination $component, $label='')
Definition: Renderer.php:268
renderSectionButton(Component\Button\Button $component, $tpl, $type)
Definition: Renderer.php:96
getPaginationRange(Component\ViewControl\Pagination $component)
Get the range of pagination-buttons to show.
Definition: Renderer.php:239
registerResources(\ILIAS\UI\Implementation\Render\ResourceRegistry $registry)
Definition: Renderer.php:371
renderMode(Component\ViewControl\Mode $component, RendererInterface $default_renderer)
Definition: Renderer.php:41
$query
$url
if($DIC->http() ->request() ->getMethod()=="GET" &&isset($DIC->http() ->request() ->getQueryParams()['tex'])) $tpl
Definition: latex.php:41
getTemplate($name, $purge_unfilled_vars, $purge_unused_blocks)
Get template of component this renderer is made for.
$base
Definition: index.php:4
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.