Loading CHANGELOG.md +14 −3 Original line number Diff line number Diff line Loading @@ -3,19 +3,30 @@ CHANGELOG 6.1.3 ----- - Retrait de la dépendance à laminas-dependency-plugin 6.1.1 ----- - PHP8.0 réautorisé 6.1.0 ----- - Compatibilité PHP8.2 6.0.15 ------ - Doctrine ORM : support de la fonction coalesce(), y compris dans un order by. - AjaxModalListener (unicaen.js) : une erreur explicite est émise si le formulaire n'a pas l'attribut requis 'action'. - AjaxModalListener (unicaen.js) : ajout de la classe CSS 'loading' sur le 'body' lors du clic sur le lien puis retrait lorsque la modale est ouverte. - AjaxModalListener (unicaen.js) : déclenchement d'un événement lors du clic sur le lien et d'un autre lorsque la modale est ouverte (noms à transmettre via les attributs 'data-event-modal-loading' et 'data-event-modal-opened' du lien). - [FIX] FormElementCollection : corrections complémentaires pour que SearchAndSelect fonctionne. 6.0.14 ------ - [FIX] FormElementCollection : forçage d'id pour éviter les doubons provoqué par le clonage (SearchAndSelect ne le supporte pas) ! - [FIX] FormElementCollection : correction d'un auto-sabotage ! 6.0.13 ------ Loading config/module.config.php +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ use UnicaenApp\Message\View\Helper\MessageHelperFactory; use UnicaenApp\Mvc\RedirectResponse; use UnicaenApp\Mvc\RedirectResponseFactory; use UnicaenApp\ORM\Query\Functions\Chr; use UnicaenApp\ORM\Query\Functions\Coalesce; use UnicaenApp\ORM\Query\Functions\CompriseEntre; use UnicaenApp\ORM\Query\Functions\PasHistorise; use UnicaenApp\ORM\Query\Functions\Replace; Loading Loading @@ -467,6 +468,7 @@ return [ 'pasHistorise' => PasHistorise::class, 'replace' => Replace::class, 'chr' => Chr::class, 'coalesce' => Coalesce::class, ], ], ], Loading public/unicaen/app/js/unicaen.js +24 −0 Original line number Diff line number Diff line Loading @@ -493,16 +493,37 @@ function AjaxModalListener(dialogDivId) var modalDialog = this.getModalDialog(); if (url && url !== "#") { $("body").addClass('loading'); // transmet à la DIV le lien cliqué (car fournit l'événement à déclencher à la soumission du formulaire) modalDialog.data('a', anchor); this.modalEventName = anchor.data('event'); // déclenchement d'un événement dont le nom est fourni par le lien cliqué (via un attribut "data-xxxx") var eventName = anchor.data('event-modal-loading'); if (eventName) { var event = jQuery.Event(eventName, {div: modalDialog, a: modalDialog.data('a')}); // console.log("Triggering '" + event.type + "' event..."); // console.log("Event object : ", event); this.eventListener.trigger(event); } // requête AJAX pour obtenir le nouveau contenu de la fenêtre modale $.get(url, {modal: 1}, $.proxy(function (data) { // remplacement du contenu de la fenêtre modale $(".modal-content", modalDialog.modal('show')).html(this.extractNewModalContent(data)); // déclenchement d'un événement dont le nom est fourni par le lien cliqué (via un attribut "data-xxxx") var eventName = anchor.data('event-modal-opened'); if (eventName) { var event = jQuery.Event(eventName, {div: modalDialog, a: modalDialog.data('a')}); console.log("Triggering '" + event.type + "' event..."); console.log("Event object : ", event); this.eventListener.trigger(event); } $("body").removeClass('loading'); }, this)); } Loading Loading @@ -569,6 +590,9 @@ function AjaxModalListener(dialogDivId) postData.append("modal", "1"); var url = form.attr('action'); if (!url) { throw new Error("Le formulaire dans la modale doit posséder un attribut 'action'"); } var isRedirect = url.indexOf("redirect=") > -1 || $("input[name=redirect]").val(); // requête AJAX de soumission du formulaire Loading src/UnicaenApp/Form/View/Helper/FormElementCollection.php +40 −48 Original line number Diff line number Diff line <?php namespace UnicaenApp\Form\View\Helper; use UnicaenApp\Form\Element\Collection; use Laminas\Form\View\Helper\FormCollection; use Laminas\Form\ElementInterface; use Laminas\Form\Element\Collection as CollectionElement; use Laminas\Form\ElementInterface; use Laminas\Form\FieldsetInterface; use Laminas\Form\LabelAwareInterface; use Laminas\Form\Element\Button; use Laminas\Form\View\Helper\FormCollection; use UnicaenApp\Form\Element\Collection; /** * Aide de vue dessinant une collection d'éléments. Loading Loading @@ -37,18 +36,13 @@ class FormElementCollection extends FormCollection protected $defaultElementHelper = 'formControlGroup'; /** * Nombre d'éléments à afficher * * @var int * Nombre d'éléments à afficher. */ protected $countElements; protected int $countElements; /** * Render a collection by iterating through all fieldsets and elements * * @param ElementInterface $element * @return string * Render a collection by iterating through all fieldsets and elements. */ public function render(ElementInterface $element): string { Loading @@ -61,9 +55,13 @@ class FormElementCollection extends FormCollection $index = 0; $markup = ''; $linkMarkup = ''; $javascript = null; $css = null; $templateMarkup = ''; $elementHelper = $this->getElementHelper(); assert(is_callable($elementHelper)); $fieldsetHelper = $this->getFieldsetHelper(); assert(is_callable($fieldsetHelper)); if ($element instanceof CollectionElement && $element->shouldCreateTemplate()) { $this->countElements = $element->getCount(); Loading @@ -80,9 +78,19 @@ class FormElementCollection extends FormCollection foreach ($element->getIterator() as $elementOrFieldset) { if ($elementOrFieldset instanceof FieldsetInterface) { $elementOrFieldset->setAttribute('data-index', $index); $markup .= $fieldsetHelper($elementOrFieldset, $this->shouldWrap()); $fieldsetHtml = $fieldsetHelper($elementOrFieldset, $this->shouldWrap()); $fieldsetHtml = str_replace('__index__', $index, $fieldsetHtml); $index++; $markup .= $fieldsetHtml; } elseif ($elementOrFieldset instanceof ElementInterface) { /** * NB : la valeur d'un id doit être unique dans un DOM. Or, en cas de collection autorisant l'ajout d'élément * (par clonage), on garantit l'unicité en concaténant le pattern '__index__', pattern qui est remplacé/incrémenté * par le moteur js de cette aide de vue (cf. plus bas). * Par ex, {@see \UnicaenApp\Form\Element\SearchAndSelect} ne fonctionne plus dans une collection en cas de doublon d'id. */ $id = $elementOrFieldset->getAttribute('id') ?: uniqid('element-'); $elementOrFieldset->setAttribute('id', $id . '-__index__'); $markup .= $elementHelper($elementOrFieldset); } } Loading Loading @@ -122,8 +130,8 @@ class FormElementCollection extends FormCollection $templateMarkup, $attributesString, $linkMarkup, $css = null, $javascript = null, $css, $javascript, ); } else { $markup .= $templateMarkup . $linkMarkup; Loading @@ -132,7 +140,7 @@ class FormElementCollection extends FormCollection return $markup; } protected function getDelLink() protected function getDelLink(): string { return '<div class="collection-delete-link">' . '<a class="btn btn-link" title="Supprimer cet élément de la collection">' . Loading @@ -141,12 +149,7 @@ class FormElementCollection extends FormCollection '</div>'; } /** * Get add link * * @return string */ protected function getAddLink() protected function getAddLink(): string { return '<div class="collection-add-link">' . '<a class="btn btn-link" title="Ajouter un élément à la collection">' . Loading @@ -155,11 +158,7 @@ class FormElementCollection extends FormCollection '</div>'; } /** * @param Collection $container * @return string */ protected function getCss($container) protected function getCss(Collection $container): string { $fieldsetId = $container->getAttribute('id'); Loading Loading @@ -192,11 +191,7 @@ EOT; return $css; } /** * @param Collection $container * @return string */ protected function getJavascript($container) protected function getJavascript(Collection $container): string { $maxEnabled = ($container->getMaxElements()) ? 'true' : 'false'; $minEnabled = ($container->getMinElements()) ? 'true' : 'false'; Loading Loading @@ -281,24 +276,21 @@ $().ready(function updateButtons() }); } }); EOT; foreach($container->getAutocomplete() as $name => $options) { $javascript .= <<<EOT $('#{$container->getAttribute('id')}').on('keyup', '.{$container->getAttribute('id')}-autocomplete', function() { $(this).autocompleteOctopus({ source: '{$options['source']}', minLength: {$options['min-length']}, delay: {$options['delay']} }); }); EOT; } // foreach($container->getAutocomplete() as $name => $options) { // $javascript .= <<<EOT //$('#{$container->getAttribute('id')}').on('keyup', '.{$container->getAttribute('id')}-autocomplete', function() { // $(this).autocompleteOctopus({ // source: '{$options['source']}', // minLength: {$options['min-length']}, // delay: {$options['delay']} // }); //}); // // //EOT; // } return '<script type="text/javascript">' . $javascript . '</script>'; } Loading src/UnicaenApp/Form/View/Helper/FormSearchAndSelect.php +28 −94 Original line number Diff line number Diff line <?php namespace UnicaenApp\Form\View\Helper; use UnicaenApp\Exception\LogicException; use UnicaenApp\Form\Element\SearchAndSelect; use Laminas\Form\Element\Text; use Laminas\Form\ElementInterface; use Laminas\Form\Exception\InvalidElementException; use Laminas\Form\View\Helper\FormText; use UnicaenApp\Form\Element\SearchAndSelect; /** * Aide de vue générant le code HTML de l'élément de formulaire du même nom. * * @author <bertrand.gauthier@unicaen.fr> * @see \UnicaenApp\Form\Element\SearchAndSelect * Aide de vue générant le code HTML de l'élément de formulaire {@see \UnicaenApp\Form\Element\SearchAndSelect}. */ class FormSearchAndSelect extends FormText { /** * @var SearchAndSelect */ protected $element; /** * @var string */ protected $autocompleteSource; /** * @var int */ protected $autocompleteMinLength = 2; /** * @var string */ protected $spinnerSource = "//gest.unicaen.fr/images/ajax-loader-r.gif"; protected SearchAndSelect $element; protected Text $autocompleteElement; protected ?string $autocompleteSource = null; protected int $autocompleteMinLength = 2; protected string $spinnerSource = "//gest.unicaen.fr/images/ajax-loader-r.gif"; /** * {@inheritdoc} */ public function __invoke(ElementInterface $element = null) { if ($element && !$element instanceof SearchAndSelect) { throw new InvalidElementException("L'élément spécifié n'est pas du type attendu."); if (! $element) { return $this; } $this->element = $element; return parent::__invoke($element); return $this->render($element); } /** * {@inheritdoc} */ public function render(ElementInterface $element): string { if (!$element instanceof SearchAndSelect) { Loading @@ -74,20 +49,22 @@ class FormSearchAndSelect extends FormText // 'label' => libellé affiché (ex: nom complet de la personne) $this->element->setName($name . "[$id]"); // render parent $markup = parent::render($this->element); $elementDomId = $this->element->getAttribute('id'); $autocompleteDomId = $elementDomId . '-autocomplete'; $autocomplete = new Text(); $autocomplete->setAttributes($this->element->getAttributes()) $this->autocompleteElement = new Text(); $this->autocompleteElement ->setAttributes($this->element->getAttributes()) ->setName($name . "[$label]") ->setAttribute('id', $autocompleteDomId) ->setAttribute('class', 'form-control form-control-sm') ->setValue($this->element->getValueLabel() ?: $this->element->getValue()); $markup .= $this->getView()->formText($autocomplete); $this->element->setAttribute('style', $this->element->getAttribute('style') . ' display:none;'); $markup = parent::render($this->element); $markup .= $this->view->formText($this->autocompleteElement); $markup .= <<<EOS <style> Loading @@ -100,34 +77,21 @@ class FormSearchAndSelect extends FormText </style> EOS; // $this->getView()->plugin('inlineScript')->appendScript($this->getJavascript()); $markup .= PHP_EOL . '<script>' . $this->getJavascript() . '</script>' . PHP_EOL; return $markup; } /** * * @return string * @throws LogicException */ public function getJavascript() protected function getJavascript(): string { if (!$this->element) { throw new LogicException("Aucun élément spécifié, appelez render() auparavant."); } $elementDomId = $this->element->getAttribute('id'); $autocompleteDomId = $elementDomId . '-autocomplete'; $js = <<<EOT // cache l'élément contenant l'id de la sélection $("#{$elementDomId}").css('display', 'none'); $autocompleteDomId = $this->autocompleteElement->getAttribute('id'); return <<<EOT $(function() { // jQuery UI autocomplete var autocomp = $("#{$autocompleteDomId}"); autocomp.autocompleteUnicaen({ // autocompleteUnicaen() définie dans "public/js/util.js" autocomp.autocompleteUnicaen({ // autocompleteUnicaen() définie dans "public/unicaen/app/js/unicaen.js" elementDomId: '$elementDomId', source: '{$this->getAutocompleteSource()}', minLength: {$this->getAutocompleteMinLength()}, Loading @@ -135,27 +99,15 @@ $(function() { }); }); EOT; return $js; } /** * * * @param string|array $autocompleteSource * @return SearchAndSelect */ public function setAutocompleteSource($autocompleteSource) public function setAutocompleteSource(string $autocompleteSource): self { $this->autocompleteSource = $autocompleteSource; return $this; } /** * * * @return string|array $autocompleteSource */ public function getAutocompleteSource() public function getAutocompleteSource(): string { if (null !== $this->autocompleteSource) { return $this->autocompleteSource; Loading @@ -163,41 +115,23 @@ EOT; return $this->element->getAutocompleteSource(); } /** * * @return int */ public function getAutocompleteMinLength() public function getAutocompleteMinLength(): int { return $this->autocompleteMinLength; } /** * * @param int $autocompleteMinLength * @return SearchAndSelect */ public function setAutocompleteMinLength($autocompleteMinLength) public function setAutocompleteMinLength(int $autocompleteMinLength): self { $this->autocompleteMinLength = $autocompleteMinLength; return $this; } /** * * @return string */ public function getSpinnerSource() public function getSpinnerSource(): string { return $this->spinnerSource; } /** * * @param string $spinnerSource * @return SearchAndSelect */ public function setSpinnerSource($spinnerSource) public function setSpinnerSource(string $spinnerSource): self { $this->spinnerSource = $spinnerSource; return $this; Loading Loading
CHANGELOG.md +14 −3 Original line number Diff line number Diff line Loading @@ -3,19 +3,30 @@ CHANGELOG 6.1.3 ----- - Retrait de la dépendance à laminas-dependency-plugin 6.1.1 ----- - PHP8.0 réautorisé 6.1.0 ----- - Compatibilité PHP8.2 6.0.15 ------ - Doctrine ORM : support de la fonction coalesce(), y compris dans un order by. - AjaxModalListener (unicaen.js) : une erreur explicite est émise si le formulaire n'a pas l'attribut requis 'action'. - AjaxModalListener (unicaen.js) : ajout de la classe CSS 'loading' sur le 'body' lors du clic sur le lien puis retrait lorsque la modale est ouverte. - AjaxModalListener (unicaen.js) : déclenchement d'un événement lors du clic sur le lien et d'un autre lorsque la modale est ouverte (noms à transmettre via les attributs 'data-event-modal-loading' et 'data-event-modal-opened' du lien). - [FIX] FormElementCollection : corrections complémentaires pour que SearchAndSelect fonctionne. 6.0.14 ------ - [FIX] FormElementCollection : forçage d'id pour éviter les doubons provoqué par le clonage (SearchAndSelect ne le supporte pas) ! - [FIX] FormElementCollection : correction d'un auto-sabotage ! 6.0.13 ------ Loading
config/module.config.php +2 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ use UnicaenApp\Message\View\Helper\MessageHelperFactory; use UnicaenApp\Mvc\RedirectResponse; use UnicaenApp\Mvc\RedirectResponseFactory; use UnicaenApp\ORM\Query\Functions\Chr; use UnicaenApp\ORM\Query\Functions\Coalesce; use UnicaenApp\ORM\Query\Functions\CompriseEntre; use UnicaenApp\ORM\Query\Functions\PasHistorise; use UnicaenApp\ORM\Query\Functions\Replace; Loading Loading @@ -467,6 +468,7 @@ return [ 'pasHistorise' => PasHistorise::class, 'replace' => Replace::class, 'chr' => Chr::class, 'coalesce' => Coalesce::class, ], ], ], Loading
public/unicaen/app/js/unicaen.js +24 −0 Original line number Diff line number Diff line Loading @@ -493,16 +493,37 @@ function AjaxModalListener(dialogDivId) var modalDialog = this.getModalDialog(); if (url && url !== "#") { $("body").addClass('loading'); // transmet à la DIV le lien cliqué (car fournit l'événement à déclencher à la soumission du formulaire) modalDialog.data('a', anchor); this.modalEventName = anchor.data('event'); // déclenchement d'un événement dont le nom est fourni par le lien cliqué (via un attribut "data-xxxx") var eventName = anchor.data('event-modal-loading'); if (eventName) { var event = jQuery.Event(eventName, {div: modalDialog, a: modalDialog.data('a')}); // console.log("Triggering '" + event.type + "' event..."); // console.log("Event object : ", event); this.eventListener.trigger(event); } // requête AJAX pour obtenir le nouveau contenu de la fenêtre modale $.get(url, {modal: 1}, $.proxy(function (data) { // remplacement du contenu de la fenêtre modale $(".modal-content", modalDialog.modal('show')).html(this.extractNewModalContent(data)); // déclenchement d'un événement dont le nom est fourni par le lien cliqué (via un attribut "data-xxxx") var eventName = anchor.data('event-modal-opened'); if (eventName) { var event = jQuery.Event(eventName, {div: modalDialog, a: modalDialog.data('a')}); console.log("Triggering '" + event.type + "' event..."); console.log("Event object : ", event); this.eventListener.trigger(event); } $("body").removeClass('loading'); }, this)); } Loading Loading @@ -569,6 +590,9 @@ function AjaxModalListener(dialogDivId) postData.append("modal", "1"); var url = form.attr('action'); if (!url) { throw new Error("Le formulaire dans la modale doit posséder un attribut 'action'"); } var isRedirect = url.indexOf("redirect=") > -1 || $("input[name=redirect]").val(); // requête AJAX de soumission du formulaire Loading
src/UnicaenApp/Form/View/Helper/FormElementCollection.php +40 −48 Original line number Diff line number Diff line <?php namespace UnicaenApp\Form\View\Helper; use UnicaenApp\Form\Element\Collection; use Laminas\Form\View\Helper\FormCollection; use Laminas\Form\ElementInterface; use Laminas\Form\Element\Collection as CollectionElement; use Laminas\Form\ElementInterface; use Laminas\Form\FieldsetInterface; use Laminas\Form\LabelAwareInterface; use Laminas\Form\Element\Button; use Laminas\Form\View\Helper\FormCollection; use UnicaenApp\Form\Element\Collection; /** * Aide de vue dessinant une collection d'éléments. Loading Loading @@ -37,18 +36,13 @@ class FormElementCollection extends FormCollection protected $defaultElementHelper = 'formControlGroup'; /** * Nombre d'éléments à afficher * * @var int * Nombre d'éléments à afficher. */ protected $countElements; protected int $countElements; /** * Render a collection by iterating through all fieldsets and elements * * @param ElementInterface $element * @return string * Render a collection by iterating through all fieldsets and elements. */ public function render(ElementInterface $element): string { Loading @@ -61,9 +55,13 @@ class FormElementCollection extends FormCollection $index = 0; $markup = ''; $linkMarkup = ''; $javascript = null; $css = null; $templateMarkup = ''; $elementHelper = $this->getElementHelper(); assert(is_callable($elementHelper)); $fieldsetHelper = $this->getFieldsetHelper(); assert(is_callable($fieldsetHelper)); if ($element instanceof CollectionElement && $element->shouldCreateTemplate()) { $this->countElements = $element->getCount(); Loading @@ -80,9 +78,19 @@ class FormElementCollection extends FormCollection foreach ($element->getIterator() as $elementOrFieldset) { if ($elementOrFieldset instanceof FieldsetInterface) { $elementOrFieldset->setAttribute('data-index', $index); $markup .= $fieldsetHelper($elementOrFieldset, $this->shouldWrap()); $fieldsetHtml = $fieldsetHelper($elementOrFieldset, $this->shouldWrap()); $fieldsetHtml = str_replace('__index__', $index, $fieldsetHtml); $index++; $markup .= $fieldsetHtml; } elseif ($elementOrFieldset instanceof ElementInterface) { /** * NB : la valeur d'un id doit être unique dans un DOM. Or, en cas de collection autorisant l'ajout d'élément * (par clonage), on garantit l'unicité en concaténant le pattern '__index__', pattern qui est remplacé/incrémenté * par le moteur js de cette aide de vue (cf. plus bas). * Par ex, {@see \UnicaenApp\Form\Element\SearchAndSelect} ne fonctionne plus dans une collection en cas de doublon d'id. */ $id = $elementOrFieldset->getAttribute('id') ?: uniqid('element-'); $elementOrFieldset->setAttribute('id', $id . '-__index__'); $markup .= $elementHelper($elementOrFieldset); } } Loading Loading @@ -122,8 +130,8 @@ class FormElementCollection extends FormCollection $templateMarkup, $attributesString, $linkMarkup, $css = null, $javascript = null, $css, $javascript, ); } else { $markup .= $templateMarkup . $linkMarkup; Loading @@ -132,7 +140,7 @@ class FormElementCollection extends FormCollection return $markup; } protected function getDelLink() protected function getDelLink(): string { return '<div class="collection-delete-link">' . '<a class="btn btn-link" title="Supprimer cet élément de la collection">' . Loading @@ -141,12 +149,7 @@ class FormElementCollection extends FormCollection '</div>'; } /** * Get add link * * @return string */ protected function getAddLink() protected function getAddLink(): string { return '<div class="collection-add-link">' . '<a class="btn btn-link" title="Ajouter un élément à la collection">' . Loading @@ -155,11 +158,7 @@ class FormElementCollection extends FormCollection '</div>'; } /** * @param Collection $container * @return string */ protected function getCss($container) protected function getCss(Collection $container): string { $fieldsetId = $container->getAttribute('id'); Loading Loading @@ -192,11 +191,7 @@ EOT; return $css; } /** * @param Collection $container * @return string */ protected function getJavascript($container) protected function getJavascript(Collection $container): string { $maxEnabled = ($container->getMaxElements()) ? 'true' : 'false'; $minEnabled = ($container->getMinElements()) ? 'true' : 'false'; Loading Loading @@ -281,24 +276,21 @@ $().ready(function updateButtons() }); } }); EOT; foreach($container->getAutocomplete() as $name => $options) { $javascript .= <<<EOT $('#{$container->getAttribute('id')}').on('keyup', '.{$container->getAttribute('id')}-autocomplete', function() { $(this).autocompleteOctopus({ source: '{$options['source']}', minLength: {$options['min-length']}, delay: {$options['delay']} }); }); EOT; } // foreach($container->getAutocomplete() as $name => $options) { // $javascript .= <<<EOT //$('#{$container->getAttribute('id')}').on('keyup', '.{$container->getAttribute('id')}-autocomplete', function() { // $(this).autocompleteOctopus({ // source: '{$options['source']}', // minLength: {$options['min-length']}, // delay: {$options['delay']} // }); //}); // // //EOT; // } return '<script type="text/javascript">' . $javascript . '</script>'; } Loading
src/UnicaenApp/Form/View/Helper/FormSearchAndSelect.php +28 −94 Original line number Diff line number Diff line <?php namespace UnicaenApp\Form\View\Helper; use UnicaenApp\Exception\LogicException; use UnicaenApp\Form\Element\SearchAndSelect; use Laminas\Form\Element\Text; use Laminas\Form\ElementInterface; use Laminas\Form\Exception\InvalidElementException; use Laminas\Form\View\Helper\FormText; use UnicaenApp\Form\Element\SearchAndSelect; /** * Aide de vue générant le code HTML de l'élément de formulaire du même nom. * * @author <bertrand.gauthier@unicaen.fr> * @see \UnicaenApp\Form\Element\SearchAndSelect * Aide de vue générant le code HTML de l'élément de formulaire {@see \UnicaenApp\Form\Element\SearchAndSelect}. */ class FormSearchAndSelect extends FormText { /** * @var SearchAndSelect */ protected $element; /** * @var string */ protected $autocompleteSource; /** * @var int */ protected $autocompleteMinLength = 2; /** * @var string */ protected $spinnerSource = "//gest.unicaen.fr/images/ajax-loader-r.gif"; protected SearchAndSelect $element; protected Text $autocompleteElement; protected ?string $autocompleteSource = null; protected int $autocompleteMinLength = 2; protected string $spinnerSource = "//gest.unicaen.fr/images/ajax-loader-r.gif"; /** * {@inheritdoc} */ public function __invoke(ElementInterface $element = null) { if ($element && !$element instanceof SearchAndSelect) { throw new InvalidElementException("L'élément spécifié n'est pas du type attendu."); if (! $element) { return $this; } $this->element = $element; return parent::__invoke($element); return $this->render($element); } /** * {@inheritdoc} */ public function render(ElementInterface $element): string { if (!$element instanceof SearchAndSelect) { Loading @@ -74,20 +49,22 @@ class FormSearchAndSelect extends FormText // 'label' => libellé affiché (ex: nom complet de la personne) $this->element->setName($name . "[$id]"); // render parent $markup = parent::render($this->element); $elementDomId = $this->element->getAttribute('id'); $autocompleteDomId = $elementDomId . '-autocomplete'; $autocomplete = new Text(); $autocomplete->setAttributes($this->element->getAttributes()) $this->autocompleteElement = new Text(); $this->autocompleteElement ->setAttributes($this->element->getAttributes()) ->setName($name . "[$label]") ->setAttribute('id', $autocompleteDomId) ->setAttribute('class', 'form-control form-control-sm') ->setValue($this->element->getValueLabel() ?: $this->element->getValue()); $markup .= $this->getView()->formText($autocomplete); $this->element->setAttribute('style', $this->element->getAttribute('style') . ' display:none;'); $markup = parent::render($this->element); $markup .= $this->view->formText($this->autocompleteElement); $markup .= <<<EOS <style> Loading @@ -100,34 +77,21 @@ class FormSearchAndSelect extends FormText </style> EOS; // $this->getView()->plugin('inlineScript')->appendScript($this->getJavascript()); $markup .= PHP_EOL . '<script>' . $this->getJavascript() . '</script>' . PHP_EOL; return $markup; } /** * * @return string * @throws LogicException */ public function getJavascript() protected function getJavascript(): string { if (!$this->element) { throw new LogicException("Aucun élément spécifié, appelez render() auparavant."); } $elementDomId = $this->element->getAttribute('id'); $autocompleteDomId = $elementDomId . '-autocomplete'; $js = <<<EOT // cache l'élément contenant l'id de la sélection $("#{$elementDomId}").css('display', 'none'); $autocompleteDomId = $this->autocompleteElement->getAttribute('id'); return <<<EOT $(function() { // jQuery UI autocomplete var autocomp = $("#{$autocompleteDomId}"); autocomp.autocompleteUnicaen({ // autocompleteUnicaen() définie dans "public/js/util.js" autocomp.autocompleteUnicaen({ // autocompleteUnicaen() définie dans "public/unicaen/app/js/unicaen.js" elementDomId: '$elementDomId', source: '{$this->getAutocompleteSource()}', minLength: {$this->getAutocompleteMinLength()}, Loading @@ -135,27 +99,15 @@ $(function() { }); }); EOT; return $js; } /** * * * @param string|array $autocompleteSource * @return SearchAndSelect */ public function setAutocompleteSource($autocompleteSource) public function setAutocompleteSource(string $autocompleteSource): self { $this->autocompleteSource = $autocompleteSource; return $this; } /** * * * @return string|array $autocompleteSource */ public function getAutocompleteSource() public function getAutocompleteSource(): string { if (null !== $this->autocompleteSource) { return $this->autocompleteSource; Loading @@ -163,41 +115,23 @@ EOT; return $this->element->getAutocompleteSource(); } /** * * @return int */ public function getAutocompleteMinLength() public function getAutocompleteMinLength(): int { return $this->autocompleteMinLength; } /** * * @param int $autocompleteMinLength * @return SearchAndSelect */ public function setAutocompleteMinLength($autocompleteMinLength) public function setAutocompleteMinLength(int $autocompleteMinLength): self { $this->autocompleteMinLength = $autocompleteMinLength; return $this; } /** * * @return string */ public function getSpinnerSource() public function getSpinnerSource(): string { return $this->spinnerSource; } /** * * @param string $spinnerSource * @return SearchAndSelect */ public function setSpinnerSource($spinnerSource) public function setSpinnerSource(string $spinnerSource): self { $this->spinnerSource = $spinnerSource; return $this; Loading