Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
typo3
qfq
Commits
6e049ecd
Commit
6e049ecd
authored
Feb 25, 2020
by
Carsten Rose
Browse files
Refs #10145: QFQ fills data-typeahead-initial-suggestion
parent
5741fc8d
Pipeline
#3331
passed with stages
in 4 minutes and 33 seconds
Changes
8
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Documentation/Manual.rst
View file @
6e049ecd
...
...
@@ -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
;;;;
...
...
extension/Classes/Core/AbstractBuildForm.php
View file @
6e049ecd
...
...
@@ -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
);
}
}
...
...
extension/Classes/Core/Constants.php
View file @
6e049ecd
...
...
@@ -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'
;
...
...
extension/Classes/Core/Database/Database.php
View file @
6e049ecd
...
...
@@ -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\HelperFil
e
;
use
IMATHUZH\Qfq\Core\
Store\Stor
e
;
/**
* 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
);
}
...
...
extension/Classes/Core/Helper/HelperFormElement.php
View file @
6e049ecd
...
...
@@ -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
:
...
...
extension/Classes/Core/Helper/OnArray.php
View file @
6e049ecd
...
...
@@ -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
extension/Classes/Core/Helper/Support.php
View file @
6e049ecd
...
...
@@ -292,8 +292,8 @@ class Support {
*
* TinyMCE: Encoding JS Attributes (keys & values) for TinyMCE needs to be encapsulated in '"' instead of '\"'.
*
* @param
$str
* @param string $modeEscape
* @param
string
$str
* @param string $modeEscape
ESCAPE_WITH_BACKSLASH | ESCAPE_WITH_HTML_QUOTE
*
* @return string
* @throws \CodeException
...
...
extension/Classes/Core/Store/FillStoreForm.php
View file @
6e049ecd
...
...
@@ -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
();
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment