<?php namespace PHPFUI\Input; class AutoComplete extends \PHPFUI\Input\Input { use \PHPFUI\Traits\Page; protected string $className; protected \PHPFUI\Input\Hidden $hidden; protected bool $noFreeForm = false; protected array $options = []; public function __construct(protected \PHPFUI\Page $page, protected $callback, string $type, string $name, ?string $label = null, ?string $value = null) { $this->hidden = new \PHPFUI\Input\Hidden($name, $value); $name .= 'Text'; parent::__construct($type, $name, $label, $value); $this->hidden->setId($this->getId() . 'hidden'); $this->add($this->hidden); $this->className = \basename(\str_replace('\\', '/', self::class)); $this->page->addTailScript('jquery.autocomplete.js'); $this->addAttribute('autocomplete', 'off'); if (isset($_POST[$this->className]) && \PHPFUI\Session::checkCSRF() && $_POST['fieldName'] == $name) { $returnValue = \json_encode(\call_user_func($this->callback, $_POST), JSON_INVALID_UTF8_IGNORE); if ($returnValue) { $this->page->setRawResponse($returnValue); } } $csrf = \PHPFUI\Session::csrf("'"); $csrfField = \PHPFUI\Session::csrfField(); $dollar = '$'; $this->options = [ 'minChars' => 3, 'type' => "'POST'", 'autoSelectFirst' => true, 'showNoSuggestionNotice' => true, 'paramName' => "'{$this->className}'", 'serviceUrl' => "'{$this->page->getBaseURL()}'", 'params' => ['fieldName' => "'{$name}'", $csrfField => $csrf], 'onSearchStart' => "function(){{$dollar}('#'+id+'hidden').val('').change()}", 'onSelect' => "function(suggestion){if(noFF){{$dollar}('#'+id).attr('placeholder',suggestion.value).attr('value','');};" . "{$dollar}('#'+id+'hidden').val(suggestion.data).change();" . "{$dollar}.ajax({type:'POST',traditional:true,data:{{$csrfField}:{$csrf},save:true,fieldName:'{$name}',{$this->className}:suggestion.data}})}", 'onInvalidateSelection' => "function(){{$dollar}('#'+id+'hidden').val('').change()}", ]; } public function addAutoCompleteOption(string $option, mixed $value) : static { $this->options[$option] = $value; return $this; } public function getAutoCompleteOption(string $option) : mixed { return $this->options[$option] ?? null; } public function getHiddenField() : \PHPFUI\Input\Hidden { return $this->hidden; } public function inReveal(bool $isInRevealModal = true) : static { return $this->addAutoCompleteOption('forceFixPosition', $isInRevealModal); } public function removeAutoCompleteOption(string $option) : static { unset($this->options[$option]); return $this; } public function setAutoCompleteOption(string $option, mixed $value) : static { $this->options[$option] = $value; return $this; } public function setNoFreeForm(bool $on = true) : static { $this->noFreeForm = $on; if ($this->noFreeForm) { $this->addAttribute('placeholder', \str_replace("'", ''', $this->value)); $this->value = ''; } else { $this->value = $this->getAttribute('placeholder'); $this->deleteAttribute('placeholder'); } return $this; } protected function getEnd() : string { $id = $this->getId(); $noFreeForm = (int)($this->noFreeForm); $this->page->addJavaScript("{$id}('{$id}','{$this->name}',{$noFreeForm})"); return parent::getEnd(); } protected function getStart() : string { $id = $this->getId(); if ($this->required) { $this->setAutoCompleteRequired($this->page, $this); } $js = "function {$id}(id,fieldName,noFreeForm){var noFF=noFreeForm;"; $js .= '$("#"+id).devbridgeAutocomplete(' . \PHPFUI\TextHelper::arrayToJS($this->options) . ')}'; $this->page->addJavaScript($js); return parent::getStart(); } }