Commit 6e049ecd authored by Carsten  Rose's avatar Carsten Rose

Refs #10145: QFQ fills data-typeahead-initial-suggestion

parent 5741fc8d
Pipeline #3331 passed with stages
in 4 minutes and 33 seconds
......@@ -3227,6 +3227,8 @@ See also at specific *FormElement* definitions.
| | | (defaults to 00:00:00 if none entered). |
+------------------------+--------+----------------------------------------------------------------------------------------------------------+
| typeAheadLimit, | string | See `input-typeahead`_ |
| typeAheadInitial | | |
| Suggestion, | | |
| typeAheadMinLength, | | |
| typeAheadSql, | | |
| typeAheadSqlPrefetch, | | |
......@@ -3540,7 +3542,7 @@ configured).
Configuration via Form / FormElement
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
All of the `typeAhead*` (except `typeAheadLdap`) and `ldap*` parameter can be specified either in
All of the `typeAhead*` (except `typeAheadLdap`, `typeAheadInitialSuggestion`) and `ldap*` parameter can be specified either in
*Form.parameter* or in *FormElement.parameter*.
SQL
......@@ -3548,7 +3550,7 @@ SQL
* *FormElement.parameter*:
* *typeAheadSql* = `SELECT ... AS 'id', ... AS 'value' FROM ... WHERE name LIKE ? OR firstName LIKE ? LIMIT 100`
* *typeAheadSql* = ``SELECT ... AS 'id', ... AS 'value' FROM ... WHERE name LIKE ? OR firstName LIKE ? LIMIT 100``
* If there is only one column in the SELECT statement, that one will be used and there is no dict (key/value pair).
* If there is no column `id` or no column `value`, then the first column becomes `id` and the second column becomes `value`.
......@@ -3556,11 +3558,17 @@ SQL
* The value, typed by the user, will be replaced on all places where a `?` appears.
* All `?` will be automatically surrounded by '%'. Therefore wildcard search is implemented: `... LIKE '%<?>%' ...`
* *typeAheadSqlPrefetch* = `SELECT firstName, ' ', lastName FROM Person WHERE id = ?`
* *typeAheadSqlPrefetch* = ``SELECT firstName, ' ', lastName FROM Person WHERE id = ?``
* If the query returns several results, only the first one is returned and displayed.
* If the query selects multiple columns, the columns are concatenated.
* *typeAheadInitialSuggestion* = ``{{!SELECT fr.id AS id, fr.name AS value FROM Fruit AS fr}}``
* Shows suggestions when the input element gets the focus, before the user starts to type anything.
* If given, *typeAheadMinLength* will be set to 0.
* Limit the number of rows via SQL ``... LIMIT ...`` clause.
LDAP
;;;;
......
......@@ -737,7 +737,8 @@ abstract class AbstractBuildForm {
// The following 'FormElement.parameter' will never be used during load (fe.type='upload'). FE_PARAMETER has been already expanded.
$skip = [FE_SQL_UPDATE, FE_SQL_INSERT, FE_SQL_DELETE, FE_SQL_AFTER, FE_SQL_BEFORE, FE_PARAMETER,
FE_FILL_STORE_VAR, FE_FILE_DOWNLOAD_BUTTON, FE_TYPEAHEAD_GLUE_INSERT, FE_TYPEAHEAD_GLUE_DELETE, FE_TYPEAHEAD_TAG_INSERT];
FE_FILL_STORE_VAR, FE_FILE_DOWNLOAD_BUTTON, FE_TYPEAHEAD_GLUE_INSERT, FE_TYPEAHEAD_GLUE_DELETE,
FE_TYPEAHEAD_TAG_INSERT, FE_TYPEAHEAD_INITIAL_SUGGESTION];
// get current data record
$primaryKey = $this->formSpec[F_PRIMARY_KEY];
......@@ -1335,6 +1336,7 @@ abstract class AbstractBuildForm {
}
}
// Check if typeAhead[Tag] needs to build
if ('' != ($typeAheadUrlParam = $this->typeAheadBuildParam($formElement))) {
if (empty($formElement[FE_INPUT_TYPE])) {
......@@ -1345,6 +1347,14 @@ abstract class AbstractBuildForm {
$formElement[FE_INPUT_AUTOCOMPLETE] = 'off'; // typeahead behaves better with 'autocomplete'='off'
}
// Collect typeAhead initial suggestion
if (!empty($formElement[FE_TYPEAHEAD_INITIAL_SUGGESTION])) {
// $formElement[FE_TYPEAHEAD_MINLENGTH] = 0; // If a suggestion is defined: minLength becomes automatically 0
$arr = $this->evaluate->parse($formElement[FE_TYPEAHEAD_INITIAL_SUGGESTION]);
$arr = $this->dbArray[$this->dbIndexData]->makeArrayDict($arr, TYPEAHEAD_SQL_KEY_NAME, API_TYPEAHEAD_VALUE, API_TYPEAHEAD_KEY, API_TYPEAHEAD_VALUE);
$attribute .= Support::doAttribute(DATA_TYPEAHEAD_INITIAL_SUGGESTION, json_encode($arr));
}
$class .= ' ' . CLASS_TYPEAHEAD;
$dataSip = $this->sip->queryStringToSip($typeAheadUrlParam, RETURN_SIP);
$attribute .= Support::doAttribute(DATA_TYPEAHEAD_SIP, $dataSip);
......@@ -1364,12 +1374,8 @@ abstract class AbstractBuildForm {
$formElement[FE_INPUT_TYPE] = 'hidden';
// Client: TAG handling expects the '$value' as a JSON string.
$kk = KeyValueStringParser::parse($value, PARAM_KEY_VALUE_DELIMITER, PARAM_LIST_DELIMITER, KVP_IF_VALUE_EMPTY_COPY_KEY);
$jj = '';
foreach ($kk as $arrKey => $arrValue) {
$jj .= ',' . json_encode(["key" => $arrKey, "value" => $arrValue]);
}
$value = '[' . substr($jj, 1) . ']';
$arr = KeyValueStringParser::parse($value, PARAM_KEY_VALUE_DELIMITER, PARAM_LIST_DELIMITER, KVP_IF_VALUE_EMPTY_COPY_KEY);
$value = OnArray::arrayToQfqJson($arr);
}
}
......
......@@ -859,6 +859,7 @@ const DATA_ENABLE_SAVE_BUTTON = 'data-enable-save-button';
const DATA_TYPEAHEAD_LIMIT = 'data-typeahead-limit';
const DATA_TYPEAHEAD_MINLENGTH = 'data-typeahead-minlength';
const DATA_TYPEAHEAD_PEDANTIC = 'data-typeahead-pedantic';
const DATA_TYPEAHEAD_INITIAL_SUGGESTION = 'data-typeahead-initial-suggestion';
const DATA_TYPEAHEAD_TAG = 'data-typeahead-tags';
const DATA_TYPEAHEAD_TAG_DELIMITER = 'data-typeahead-tag-delimiters';
......@@ -870,8 +871,6 @@ const CLASS_FORM_ELEMENT_EDIT = 'qfq-form-element-edit';
const CLASS_FORM_ELEMENT_AUTO_GROW = 'qfq-auto-grow';
const ATTRIBUTE_DATA_MAX_HEIGHT = 'data-max-height';
// BuildForm
const SYMBOL_NEW = 'new';
const SYMBOL_EDIT = 'edit';
......@@ -1240,6 +1239,7 @@ const FE_LDAP_USE_BIND_CREDENTIALS = F_LDAP_USE_BIND_CREDENTIALS;
const FE_TYPEAHEAD_LIMIT = F_TYPEAHEAD_LIMIT;
const FE_TYPEAHEAD_MINLENGTH = F_TYPEAHEAD_MINLENGTH;
const FE_TYPEAHEAD_PEDANTIC = F_TYPEAHEAD_PEDANTIC;
const FE_TYPEAHEAD_INITIAL_SUGGESTION = 'typeAheadInitialSuggestion';
const FE_TYPEAHEAD_TAG = 'typeAheadTag';
const FE_TYPEAHEAD_TAG_DELIMITER = 'typeAheadTagDelimiter';
const FE_TYPEAHEAD_GLUE_INSERT = 'typeAheadGlueInsert';
......
......@@ -8,13 +8,13 @@
namespace IMATHUZH\Qfq\Core\Database;
use IMATHUZH\Qfq\Core\Store\Store;
use IMATHUZH\Qfq\Core\Helper\Logger;
use IMATHUZH\Qfq\Core\Helper\BindParam;
use IMATHUZH\Qfq\Core\Helper\HelperFile;
use IMATHUZH\Qfq\Core\Helper\HelperFormElement;
use IMATHUZH\Qfq\Core\Helper\Logger;
use IMATHUZH\Qfq\Core\Helper\OnArray;
use IMATHUZH\Qfq\Core\Helper\HelperFile;
use IMATHUZH\Qfq\Core\Store\Store;
/**
* Class Database
......@@ -932,10 +932,12 @@ class Database {
}
/**
* $arr will be converted to a two column array with keys $keyName1 and $keyName2.
* $arr might contain one or more columns.
* Only when $keyName1 and $keyName2 exist, those will be used. Else the first column becomes $keyName1 and the
* second becomes $keyName2. If there is only one column, that column will be doubled.
* $arr = [ 0 => [ $srcColumn1 => $value0_1, $srcColumn2 => $value0_2 ], 1 => [ $srcColumn1 => $value1_1, $srcColumn2 => $value1_2 ], ...]
*
* $arr will be converted to a two column array with keys $destColumn1 and $destColumn2.
* If $destColumn1 or $destColumn2 is empty, take $srcColumn1, $srcColumn2 as names.
* $arr might contain one or more columns. Only the first two columns are used.
* If there is only one column, that column will be doubled.
*
* @param array $arr
* @param string $srcColumn1
......@@ -947,6 +949,11 @@ class Database {
*/
public function makeArrayDict(array $arr, $srcColumn1, $srcColumn2, $destColumn1 = '', $destColumn2 = '') {
if ($arr == array() || $arr === null) {
return array();
}
// Set defaults
if ($destColumn1 == '') {
$destColumn1 = $srcColumn1;
}
......@@ -955,12 +962,7 @@ class Database {
$destColumn2 = $srcColumn2;
}
$new = array();
if ($arr == array() || $arr === null) {
return array();
}
// Set final column names
$row = $arr[0];
$keys = array_keys($row);
if (count($row) < 2) {
......@@ -974,9 +976,11 @@ class Database {
$column2 = $keys[1];
}
$new = array();
$row = array_shift($arr);
while (null !== $row) {
$new[] = [$destColumn1 => $row[$column1], $destColumn2 => $row[$column2]];
// $new[] = [$destColumn1 => htmlentities($row[$column1], ENT_QUOTES), $destColumn2 => htmlentities($row[$column2], ENT_QUOTES)];
$row = array_shift($arr);
}
......@@ -1028,8 +1032,7 @@ class Database {
try {
$this->playMultiQuery($query);
}
catch (\CodeException $e) {
} catch (\CodeException $e) {
throw new \CodeException("Error playing $filename", ERROR_PLAY_SQL_FILE);
}
......
......@@ -718,7 +718,6 @@ EOF;
$attribute .= Support::doAttribute('required', 'required');
break;
case FE_MODE_READONLY:
// $attribute .= Support::doAttribute($feMode, $feMode);
$attribute .= Support::doAttribute('disabled', 'disabled');
break;
default:
......
......@@ -427,4 +427,27 @@ class OnArray {
public static function getMd5(array $data) {
return md5(implode($data));
}
/**
* Converts a one dimensional array to JSON array. The 'key' and 'value' will names are hardcoded:
*
* Return: [ { 'key': $key[0], 'value': $value[0] }, { 'key': $key[1], 'value': $value[2] }, ... ]
*
* @param array $arr
* @param bool $flagHtmlEntity true|false
* @return string
*/
public static function arrayToQfqJson(array $arr, $flagHtmlEntity = false) {
$json = '';
foreach ($arr as $arrKey => $arrValue) {
if ($flagHtmlEntity) {
$arrKey = htmlentities($arrKey, ENT_QUOTES);
$arrValue = htmlentities($arrValue, ENT_QUOTES);
}
$json .= ',' . json_encode(["key" => $arrKey, "value" => $arrValue]);
}
return '[' . substr($json, 1) . ']';
}
}
\ No newline at end of file
......@@ -292,8 +292,8 @@ class Support {
*
* TinyMCE: Encoding JS Attributes (keys & values) for TinyMCE needs to be encapsulated in '&quot;' instead of '\"'.
*
* @param $str
* @param string $modeEscape
* @param string $str
* @param string $modeEscape ESCAPE_WITH_BACKSLASH | ESCAPE_WITH_HTML_QUOTE
*
* @return string
* @throws \CodeException
......
......@@ -175,7 +175,7 @@ class FillStoreForm {
// The following will never be used during load (fe.type='upload').
$skip = [FE_SLAVE_ID, FE_SQL_UPDATE, FE_SQL_INSERT, FE_SQL_DELETE, FE_SQL_AFTER, FE_SQL_BEFORE, FE_PARAMETER,
FE_VALUE, FE_FILL_STORE_VAR, FE_TYPEAHEAD_GLUE_INSERT, FE_TYPEAHEAD_GLUE_DELETE, FE_TYPEAHEAD_TAG_INSERT];
FE_VALUE, FE_FILL_STORE_VAR, FE_TYPEAHEAD_GLUE_INSERT, FE_TYPEAHEAD_GLUE_DELETE, FE_TYPEAHEAD_TAG_INSERT, FE_TYPEAHEAD_INITIAL_SUGGESTION];
$html = '';
$newValues = array();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment