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
e753f8cf
Commit
e753f8cf
authored
Aug 24, 2018
by
Carsten Rose
Browse files
dnd update: update of the 'ord' values implemented. Check documentation how to use it.
parent
35053677
Pipeline
#751
passed with stage
in 1 minute and 34 seconds
Changes
5
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
extension/Documentation/Manual.rst
View file @
e753f8cf
...
...
@@ -6440,7 +6440,7 @@ Manually sorting and ordering of elements via `HTML5 drag and drop` is supported
should be represented by a database record with an order column. If the elements are unordered, they will be ordered after
the first 'drag and drop' move of an element.
Functionality
is
divide
d
into:
Functionality divide
s
into:
* Display list: the records will be displayed via QFQ/report.
* Sort records: updates of the order column are managed by a specific definition form. The form is not a regular form
...
...
@@ -6450,16 +6450,16 @@ Functionality is divided into:
Part 1: Display list
''''''''''''''''''''
Display the list of elements via a regular QFQ content record. All 'drag and drop' elements have to be nested by a
n
HTML
element:
Display the list of elements via a regular QFQ content record. All 'drag and drop' elements
together
have to be nested by a HTML
element. Such HTML
element:
* With `class="qfq-dnd-sort"`.
* With a form name: `{{'form=<form name>' AS _data-dnd-api}}`
* Only direct children of such element can be dragged.
* With a form name: `{{'form=<form name>' AS _data-dnd-api}}`
(will be replaced by QFQ)
* Only
*
direct
*
children of such element can be dragged.
* Every children needs a unique identifier `data-dnd-id="<unique>"`. Typically this is the corresponding record id.
* The record needs a dedicated order column, which will be updated through API calls in time.
A `<div>` example HTML output: ::
A `<div>` example HTML output
(HTML send to the browser)
: ::
<div class="qfq-dnd-sort" data-dnd-api="typo3conf/ext/qfq/qfq/api/dragAndDrop.php?s=badcaffee1234">
<div class="anyClass" id="<uniq1>" data-dnd-id="55">
...
...
@@ -6488,7 +6488,7 @@ A typical QFQ report which generates those `<div>` HTML: ::
A `<table>` based setup is also possible. Note the attribute `data-columns="3"` - those generates a dropzone
which the same width as the outer table. ::
which the same
column
width as the outer table. ::
<table>
<tbody class="qfq-dnd-sort" data-dnd-api="typo3conf/ext/qfq/qfq/api/dragAndDrop.php?s=badcaffee1234" data-columns="3">
...
...
@@ -6516,10 +6516,32 @@ A typical QFQ report which generates those HTML: ::
tail = </tbody><table>
}
Show / update order value in the browser
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
The 'drag and drop' action does not trigger a reload of the page. In case the order number is shown and the user does
a 'drag and drop', the order number shows the old. To update the dragable elements with the latest order number, a
predefined html id has to be assigned them. After an update, all changed order number (referenced by the html id) will
be updated via AJAX.
The html id per element is defined by `qfq-dnd-ord-id-<id>` where `<id>` is the record id. Same example as above, but
with an updated `n.ord` column: ::
10 {
sql = SELECT '<tr id="anytag-', n.id,'" data-dnd-id="', n.id,'" data-columns="3">' , n.id AS '_+td', n.note AS '_+td',
'<td id="qfq-dnd-ord-id-', n.id, '">', n.ord, '</td></tr>'
FROM Note AS n
WHERE grId=28
ORDER BY n.ord
head = <table><tbody class="qfq-dnd-sort" {{'form=dndSortNote&grId=28' AS _data-dnd-api}} data-columns="3">
tail = </tbody><table>
}
Part 2: Sort records
''''''''''''''''''''
A dedicated `Form`, without any `FormElements`, is used to define the database update definition.
A dedicated `Form`, without any `FormElements`, is used to define the
reorder logic (
database update definition
)
.
Fields:
...
...
@@ -6548,6 +6570,8 @@ The form related to the example of part 1 ('div' or 'table'): ::
Form.parameter: orderColumn = ord
Form.parameter: dragAndDropOrderSql = {{!SELECT n.id AS id, n.ord AS ord FROM Note AS n WHERE n.grId={{grId:S0}} ORDER BY n.ord}}
Re-Order:
QFQ iterates over the result set of `dragAndDropOrderSql`. The value of column `id` have to correspond to the dragged HTML
element (given by `data-dnd-id`). Reordering always start with `orderInterval` and is incremented by `orderInterval` with each
record of the result set. The client reports a) the id of the dragged HTML element, b) the id of the hovered element and
...
...
extension/qfq/api/dragAndDrop.php
View file @
e753f8cf
...
...
@@ -59,6 +59,7 @@ try {
$qfq
=
new
QuickFormQuery
([
'bodytext'
=>
''
]);
$data
=
$qfq
->
dragAndDrop
();
$answer
=
array_merge
(
$data
,
$answer
);
$answer
[
API_STATUS
]
=
API_ANSWER_STATUS_SUCCESS
;
$answer
[
API_MESSAGE
]
=
'reorder: success'
;
...
...
@@ -66,7 +67,6 @@ try {
// $answer[API_ELEMENT_UPDATE] = $data[API_ELEMENT_UPDATE];
// unset($answer[API_FORM_UPDATE][API_ELEMENT_UPDATE]);
// $answer[API_ELEMENT_UPDATE] = [ 'dynamic-125' => [ 'content' => 'latest news', 'attr' => [ 'title' => 'latest title'] ] ];
$answer
[
'elementUpdate'
]
=
[
'dynamic-125'
=>
[
'content'
=>
'latest news'
,
'attr'
=>
[
'title'
=>
'latest title'
]
]
];
}
catch
(
qfq\UserFormException
$e
)
{
$answer
[
API_MESSAGE
]
=
$e
->
formatMessage
();
...
...
extension/qfq/qfq/Constants.php
View file @
e753f8cf
...
...
@@ -1544,4 +1544,5 @@ const DND_COLUMN_ID = 'id';
const
DND_COLUMN_ORD
=
'ord'
;
const
DND_COLUMN_ORD_NEW
=
'ordNew'
;
const
DND_DATA_DND_API
=
'data-dnd-api'
;
const
DND_ORD_HTML_ID_PREFIX
=
'qfq-dnd-ord-id-'
;
extension/qfq/qfq/QuickFormQuery.php
View file @
e753f8cf
...
...
@@ -319,6 +319,7 @@ class QuickFormQuery {
private
function
doForm
(
$formMode
)
{
$data
=
''
;
$foundInStore
=
''
;
$flagApiStructureReGroup
=
true
;
// Fill STORE_FORM
if
(
$formMode
===
FORM_UPDATE
||
$formMode
===
FORM_SAVE
||
$formMode
===
FORM_DRAG_AND_DROP
)
{
...
...
@@ -527,7 +528,8 @@ class QuickFormQuery {
$formAction
->
elements
(
$recordId
,
$this
->
feSpecAction
,
FE_TYPE_BEFORE_LOAD
);
$dragAndDrop
=
new
DragAndDrop
(
$this
->
formSpec
);
$dragAndDrop
->
process
();
$data
=
$dragAndDrop
->
process
();
$flagApiStructureReGroup
=
false
;
$formAction
->
elements
(
$recordId
,
$this
->
feSpecAction
,
FE_TYPE_AFTER_LOAD
);
break
;
...
...
@@ -536,7 +538,7 @@ class QuickFormQuery {
throw
new
CodeException
(
"This statement should never be reached"
,
ERROR_CODE_SHOULD_NOT_HAPPEN
);
}
if
(
is_array
(
$data
))
{
if
(
$flagApiStructureReGroup
&&
is_array
(
$data
))
{
// $data['element-update']=...
$data
=
$this
->
groupElementUpdateEntries
(
$data
);
}
...
...
@@ -717,7 +719,7 @@ class QuickFormQuery {
unlink
(
$file
);
}
else
{
$form
[
FORM_LOG_FILE
.
'_'
.
$mode
]
=
$file
;
$form
[
FORM_LOG_ACTIVE
]
=
1
;
$form
[
FORM_LOG_ACTIVE
]
=
1
;
}
}
}
...
...
@@ -1380,9 +1382,7 @@ class QuickFormQuery {
*/
public
function
dragAndDrop
()
{
$json
=
$this
->
doForm
(
FORM_DRAG_AND_DROP
);
return
$json
;
return
$this
->
doForm
(
FORM_DRAG_AND_DROP
);
}
/**
...
...
extension/qfq/qfq/form/DragAndDrop.php
View file @
e753f8cf
...
...
@@ -86,19 +86,34 @@ class DragAndDrop {
return
[];
}
$this
->
reorder
(
$this
->
formSpec
[
F_DRAG_AND_DROP_ORDER_SQL
],
$dragId
,
$setTo
,
$hoverId
,
$orderColumn
,
$orderInterval
,
$this
->
formSpec
[
F_TABLE_NAME
]);
$data
=
$this
->
reorder
(
$this
->
formSpec
[
F_DRAG_AND_DROP_ORDER_SQL
],
$dragId
,
$setTo
,
$hoverId
,
$orderColumn
,
$orderInterval
,
$this
->
formSpec
[
F_TABLE_NAME
]);
return
[]
;
return
$data
;
}
/**
* @param array $rows
* @param $dragId
* @param $setTo
* @param $hoverId
* @param $orderColumn
* @param $orderInterval
* @param $tableName
* Calculate new ord values. The array rows$ contains the old order with
* [
* [
* [DND_COLUMN_ID] => 1,
* [DND_COLUMN_ORD] => 10
* ], [
* [DND_COLUMN_ID] => 2,
* [DND_COLUMN_ORD] => 20
* ],
* ...
* ]
*
* @param array $rows Array with id/ord in the old order.
* @param int $dragId Id of the element which has been drag'ed
* @param string $setTo DND_SET_TO_BEFORE|DND_SET_TO_AFTER Indicates if the drop zone is before or after the $hoverId
* @param int $hoverId Id of element where the drag'ed element has been dropped on.
* @param string $orderColumn Table column where to save the new calculated order.
* @param int $orderInterval Order increment.
* @param string $tableName Table name where to update the order records.
* @return array Array with html-id references to update order values in the browser. Check PROTOCOL.md for 'element-update'.
*
* @throws CodeException
* @throws DbException
* @throws UserFormException
...
...
@@ -106,6 +121,7 @@ class DragAndDrop {
private
function
reorder
(
array
$rows
,
$dragId
,
$setTo
,
$hoverId
,
$orderColumn
,
$orderInterval
,
$tableName
)
{
$ord
=
$orderInterval
;
$ordDragOld
=
-
1
;
$data
=
array
();
// Reorder. Get index for 'drag' and 'hover'
foreach
(
$rows
as
$key
=>
$row
)
{
...
...
@@ -121,43 +137,52 @@ class DragAndDrop {
switch
(
$setTo
)
{
case
DND_SET_TO_BEFORE
:
$this
->
setNewOrder
(
$tableName
,
$orderColumn
,
$dragId
,
$ordDragOld
,
$ord
);
$data
=
$this
->
setNewOrder
(
$tableName
,
$orderColumn
,
$dragId
,
$ordDragOld
,
$ord
,
$data
);
$ord
+=
$orderInterval
;
$this
->
setNewOrder
(
$tableName
,
$orderColumn
,
$row
[
DND_COLUMN_ID
],
$row
[
DND_COLUMN_ORD
],
$ord
);
$data
=
$this
->
setNewOrder
(
$tableName
,
$orderColumn
,
$row
[
DND_COLUMN_ID
],
$row
[
DND_COLUMN_ORD
],
$ord
,
$data
);
break
;
case
DND_SET_TO_AFTER
:
$this
->
setNewOrder
(
$tableName
,
$orderColumn
,
$row
[
DND_COLUMN_ID
],
$row
[
DND_COLUMN_ORD
],
$ord
);
$data
=
$this
->
setNewOrder
(
$tableName
,
$orderColumn
,
$row
[
DND_COLUMN_ID
],
$row
[
DND_COLUMN_ORD
],
$ord
,
$data
);
$ord
+=
$orderInterval
;
$this
->
setNewOrder
(
$tableName
,
$orderColumn
,
$dragId
,
$ordDragOld
,
$ord
);
$data
=
$this
->
setNewOrder
(
$tableName
,
$orderColumn
,
$dragId
,
$ordDragOld
,
$ord
,
$data
);
break
;
default
:
throw
new
CodeException
(
'Unkown setTo string'
,
$setTo
,
ERROR_UNKNOWN_TOKEN
);
}
}
else
{
$this
->
setNewOrder
(
$tableName
,
$orderColumn
,
$row
[
DND_COLUMN_ID
],
$row
[
DND_COLUMN_ORD
],
$ord
);
$data
=
$this
->
setNewOrder
(
$tableName
,
$orderColumn
,
$row
[
DND_COLUMN_ID
],
$row
[
DND_COLUMN_ORD
],
$ord
,
$data
);
}
$ord
+=
$orderInterval
;
}
return
$data
;
}
/**
* @param $tableName
* @param $orderColumn
* @param $id
* @param $ordOld
* @param $ordNew
* @param string $tableName
* @param string $orderColumn
* @param int $id
* @param int $ordOld
* @param int $ordNew
* @param array $data
* @return array
* @throws CodeException
* @throws DbException
* @throws UserFormException
*/
private
function
setNewOrder
(
$tableName
,
$orderColumn
,
$id
,
$ordOld
,
$ordNew
)
{
private
function
setNewOrder
(
$tableName
,
$orderColumn
,
$id
,
$ordOld
,
$ordNew
,
array
$data
)
{
if
(
$ordNew
==
$ordOld
)
{
return
;
return
$data
;
}
$this
->
db
->
sql
(
"UPDATE
$tableName
SET
$orderColumn
=? WHERE id=?"
,
ROW_REGULAR
,
[
$ordNew
,
$id
]);
// Converting to string is necessary: JSON detects int else.
$data
[
API_ELEMENT_UPDATE
][
DND_ORD_HTML_ID_PREFIX
.
$id
][
API_ELEMENT_CONTENT
]
=
(
string
)
$ordNew
;
return
$data
;
}
}
\ No newline at end of file
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