Skip to content

Commit

Permalink
Merge pull request #578 from klees/trunk_ui_cleanup_binding_magic
Browse files Browse the repository at this point in the history
UI: cleanup magic for signal-mechanism
  • Loading branch information
Amstutz authored Jul 25, 2017
2 parents 4edc432 + 003b13c commit 91abdff
Show file tree
Hide file tree
Showing 15 changed files with 169 additions and 108 deletions.
13 changes: 12 additions & 1 deletion src/UI/Component/JavaScriptBindable.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,21 @@ interface JavaScriptBindable {
* });
*
* @param \Closure $binder
* @param self
* @return self
*/
public function withOnLoadCode(\Closure $binder);

/**
* Add some onload-code to the component instead of replacing the existing one.
*
* Must work like getOnLoadCode was called and the result of the existing binder
* (if any) and the result of the new binder are concatenated in a new binder.
*
* @param \Closure $binder
* @return self
*/
public function withAdditionalOnLoadCode(\Closure $binder);

/**
* Get the currently bound on load code.
*
Expand Down
4 changes: 2 additions & 2 deletions src/UI/Component/Triggerable.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*
* @package ILIAS\UI\Component
*/
interface Triggerable {
interface Triggerable extends JavaScriptBindable {

/**
* Get a component like this but reset (regenerate) its signals.
Expand All @@ -21,4 +21,4 @@ interface Triggerable {
*/
public function withResetSignals();

}
}
5 changes: 2 additions & 3 deletions src/UI/Component/Triggerer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*
* @package ILIAS\UI\Component
*/
interface Triggerer {
interface Triggerer extends JavaScriptBindable {

/**
* Get a component like this but reset any triggered signals of other components
Expand All @@ -26,5 +26,4 @@ public function withResetTriggeredSignals();
* @return TriggeredSignalInterface[]
*/
public function getTriggeredSignals();

}
}
10 changes: 0 additions & 10 deletions src/UI/Implementation/Component/Button/Renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,6 @@ protected function renderClose($component) {

protected function maybeRenderId(Component\Component $component, $tpl) {
$id = $this->bindJavaScript($component);
// Check if the button is acting as triggerer
if ($component instanceof Component\Triggerer && count($component->getTriggeredSignals())) {
$id = ($id === null) ? $this->createId() : $id;
$this->triggerRegisteredSignals($component, $id);
}
if ($id !== null) {
$tpl->setCurrentBlock("with_id");
$tpl->setVariable("ID", $id);
Expand All @@ -128,11 +123,6 @@ protected function renderMonth(Component\Button\Month $component, RendererInterf

$id = $this->bindJavaScript($component);

// Check if the button is acting as triggerer
if ($component instanceof Component\Triggerer && count($component->getTriggeredSignals())) {
$id = ($id === null) ? $this->createId() : $id;
$this->triggerRegisteredSignals($component, $id);
}
if ($id !== null) {
$tpl->setCurrentBlock("with_id");
$tpl->setVariable("ID", $id);
Expand Down
5 changes: 0 additions & 5 deletions src/UI/Implementation/Component/Dropdown/Renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,6 @@ protected function renderItems($items, $tpl, $default_renderer)

protected function maybeRenderId(Component\Component $component, $tpl, $block, $template_var) {
$id = $this->bindJavaScript($component);
// Check if the component is acting as triggerer
if ($component instanceof Component\Triggerer && count($component->getTriggeredSignals())) {
$id = ($id === null) ? $this->createId() : $id;
$this->triggerRegisteredSignals($component, $id);
}
if ($id !== null) {
$tpl->setCurrentBlock($block);
$tpl->setVariable($template_var, $id);
Expand Down
4 changes: 0 additions & 4 deletions src/UI/Implementation/Component/Glyph/Renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ public function render(Component\Component $component, RendererInterface $defaul
$id = $this->bindJavaScript($component);

$tpl->touchBlock($component->getType());
if ($component instanceof Component\Triggerer && count($component->getTriggeredSignals())) {
$id = ($id === null) ? $this->createId() : $id;
$this->triggerRegisteredSignals($component, $id);
}

if ($id !== null) {
$tpl->setCurrentBlock("with_id");
Expand Down
15 changes: 15 additions & 0 deletions src/UI/Implementation/Component/JavaScriptBindable.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ public function withOnLoadCode(\Closure $binder) {
return $clone;
}

/**
* @see \ILIAS\UI\Component\JavaScriptBindable::withAdditionalOnLoadCode
*/
public function withAdditionalOnLoadCode(\Closure $binder) {
$current_binder = $this->getOnLoadCode();
if ($current_binder === null) {
return $this->withOnLoadCode($binder);
}

$this->checkBinder($binder);
return $this->withOnLoadCode(function($id) use ($current_binder, $binder) {
return $current_binder($id)."\n".$binder($id);
});
}

/**
* @see \ILIAS\UI\Component\JavaScriptBindable::getOnLoadCode
*/
Expand Down
49 changes: 31 additions & 18 deletions src/UI/Implementation/Component/Modal/Renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,27 +47,43 @@ public function registerResources(ResourceRegistry $registry) {
* @param Component\Modal\Modal $modal
* @param string $id
*/
protected function registerSignals(Component\Modal\Modal $modal, $id) {
protected function registerSignals(Component\Modal\Modal $modal) {
$show = $modal->getShowSignal();
$close = $modal->getCloseSignal();
$js = $this->getJavascriptBinding();
$options = json_encode(array(
'ajaxRenderUrl' => $modal->getAsyncRenderUrl(),
'keyboard' => $modal->getCloseWithKeyboard(),
));
$js->addOnLoadCode("
$(document).on('{$show}', function() { il.UI.modal.showModal('{$id}', {$options}); return false; });
$(document).on('{$close}', function() { il.UI.modal.closeModal('{$id}'); return false; });"
);
// ATTENTION, ATTENTION:
// with(Additional)OnLoadCode opens a wormhole into the future, where some unspecified
// entity magically created an id for the component that can be used to refer to it
// via javascript.
// This replaced a pattern, where an id was created manually and the java script
// code was manually inserted to the (now internal) js-binding of the
// AbstractComponentRenderer. (see commit 192144fd1f0e040cadc0149c3dc15fbc4b67858e).
// The wormhole solution is considered superior over the manual creation of ids because:
// * withAdditionalOnLoadCode introduces no new principles to the UI framework but reuses
// an existing one
// * withAdditionalOnLoadCode does not require it to expose internals (js-binding) from
// the AbstractComponentRenderer and thus does have less coupling
// * withAdditionalOnLoadCode allows the framework to decide, when ids are actually
// created
// * since withAdditionalOnLoadCode refers to some yet unknown future, it disencourages
// tempering with the id _here_.
return $modal->withAdditionalOnLoadCode(function($id) use ($show, $close, $options) {
return
"$(document).on('{$show}', function() { il.UI.modal.showModal('{$id}', {$options}); return false; });".
"$(document).on('{$close}', function() { il.UI.modal.closeModal('{$id}'); return false; });";
});
}

/**
* @param Component\Modal\Modal $modal
* @return string
*/
protected function renderAsync(Component\Modal\Modal $modal) {
$id = $this->createId();
$this->registerSignals($modal, $id);
$modal = $this->registerSignals($modal);
$id = $this->bindJavaScript($modal);
return "<span id='{$id}'></span>";
}

Expand All @@ -79,9 +95,8 @@ protected function renderAsync(Component\Modal\Modal $modal) {
*/
protected function renderInterruptive(Component\Modal\Interruptive $modal, RendererInterface $default_renderer) {
$tpl = $this->getTemplate('tpl.interruptive.html', true, true);
$id = $this->createId();
$this->registerSignals($modal, $id);
$this->triggerRegisteredSignals($modal, $id);
$modal = $this->registerSignals($modal);
$id = $this->bindJavaScript($modal);
$tpl->setVariable('ID', $id);
$tpl->setVariable('FORM_ACTION', $modal->getFormAction());
$tpl->setVariable('TITLE', $modal->getTitle());
Expand Down Expand Up @@ -113,9 +128,8 @@ protected function renderInterruptive(Component\Modal\Interruptive $modal, Rende
*/
protected function renderRoundTrip(Component\Modal\RoundTrip $modal, RendererInterface $default_renderer) {
$tpl = $this->getTemplate('tpl.roundtrip.html', true, true);
$id = $this->createId();
$this->registerSignals($modal, $id);
$this->triggerRegisteredSignals($modal, $id);
$modal = $this->registerSignals($modal);
$id = $this->bindJavaScript($modal);
$tpl->setVariable('ID', $id);
$tpl->setVariable('TITLE', $modal->getTitle());
foreach ($modal->getContent() as $content) {
Expand All @@ -141,11 +155,10 @@ protected function renderRoundTrip(Component\Modal\RoundTrip $modal, RendererInt
*/
protected function renderLightbox(Component\Modal\Lightbox $modal, RendererInterface $default_renderer) {
$tpl = $this->getTemplate('tpl.lightbox.html', true, true);
$id = $this->createId();
$this->registerSignals($modal, $id);
$this->triggerRegisteredSignals($modal, $id);
$modal = $this->registerSignals($modal);
$id = $this->bindJavaScript($modal);
$tpl->setVariable('ID', $id);
$id_carousel = $this->createId();
$id_carousel = "{$id}_carousel";
$pages = $modal->getPages();
$tpl->setVariable('TITLE', $pages[0]->getTitle());
$tpl->setVariable('ID_CAROUSEL', $id_carousel);
Expand Down
5 changes: 4 additions & 1 deletion src/UI/Implementation/Component/Popover/Popover.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use \ILIAS\UI\Component;
use ILIAS\UI\Component\Signal;
use ILIAS\UI\Implementation\Component\ComponentHelper;
use ILIAS\UI\Implementation\Component\JavaScriptBindable;
use ILIAS\UI\Implementation\Component\SignalGeneratorInterface;

/**
Expand All @@ -16,6 +17,8 @@
abstract class Popover implements Component\Popover\Popover {

use ComponentHelper;
use JavaScriptBindable;

/**
* @var string
*/
Expand Down Expand Up @@ -155,4 +158,4 @@ protected function initSignals() {
$this->show_signal = $this->signal_generator->create();
$this->replace_content_signal = $this->signal_generator->create("ILIAS\\UI\\Implementation\\Component\\Popover\\ReplaceContentSignal");
}
}
}
42 changes: 26 additions & 16 deletions src/UI/Implementation/Component/Popover/Renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,39 +23,49 @@ public function render(Component\Component $component, RendererInterface $defaul
$tpl = $this->getTemplate('tpl.popover.html', true, true);
$tpl->setVariable('FORCE_RENDERING', '');
/** @var Component\Popover\Popover $component */

$options = array(
'title' => $this->escape($component->getTitle()),
'placement' => $component->getPosition(),
'multi' => true,
'template' => str_replace('"', '\"', $tpl->get()),
);
// Check if the content is rendered async or via DOM
$content_id = $this->createId();
if ($component->getAsyncContentUrl()) {

$is_async = $component->getAsyncContentUrl();
if ($is_async) {
$options['type'] = 'async';
$options['url'] = $component->getAsyncContentUrl();
} else {
$options['url'] = "#{$content_id}";
}
$options = json_encode($options);

$show = $component->getShowSignal();
$this->getJavascriptBinding()->addOnLoadCode("
$(document).on('{$show}', function(event, signalData) {
il.UI.popover.showFromSignal(signalData, JSON.parse('{$options}'));
});");
$replace = $component->getReplaceContentSignal();
$this->getJavascriptBinding()->addOnLoadCode("
$(document).on('{$replace}', function(event, signalData) {
il.UI.popover.replaceContentFromSignal('{$show}', signalData);
});");

$component = $component->withAdditionalOnLoadCode(function($id) use ($options, $show, $replace, $is_async) {
if (!$is_async) {
$options["url"] = "#{$id}";
}
$options = json_encode($options);

return
"$(document).on('{$show}', function(event, signalData) {
il.UI.popover.showFromSignal(signalData, JSON.parse('{$options}'));
});".
"$(document).on('{$replace}', function(event, signalData) {
il.UI.popover.replaceContentFromSignal('{$show}', signalData);
});";
});

$id = $this->bindJavaScript($component);

if ($component->getAsyncContentUrl()) {
return '';
}

if ($component instanceof Component\Popover\Standard) {
return $this->renderStandardPopover($component, $default_renderer, $content_id);
return $this->renderStandardPopover($component, $default_renderer, $id);
} else {
if ($component instanceof Component\Popover\Listing) {
return $this->renderListingPopover($component, $default_renderer, $content_id);
return $this->renderListingPopover($component, $default_renderer, $id);
}
}

Expand Down
7 changes: 1 addition & 6 deletions src/UI/Implementation/Component/ViewControl/Renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,6 @@ protected function renderSectionButton(Component\Button\Button $component, $tpl,

protected function maybeRenderId(Component\Component $component, $tpl, $block, $template_var) {
$id = $this->bindJavaScript($component);
// Check if the component is acting as triggerer
if ($component instanceof Component\Triggerer && count($component->getTriggeredSignals())) {
$id = ($id === null) ? $this->createId() : $id;
$this->triggerRegisteredSignals($component, $id);
}
if ($id !== null) {
$tpl->setCurrentBlock($block);
$tpl->setVariable($template_var, $id);
Expand All @@ -128,4 +123,4 @@ protected function getComponentInterfaceName() {

}

}
}
Loading

0 comments on commit 91abdff

Please sign in to comment.