<?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();
}
}