Loading core/includes/common.inc +7 −143 Changes for core/includes/common.inc: 7 added lines, 143 removed lines. Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\CacheTagsPurgeInterface; use Drupal\Core\DrupalKernel; use Drupal\Core\Render\Element\Table; /** * @defgroup php_wrappers PHP wrapper functions Loading Loading @@ -127,153 +128,16 @@ function base_path() { /** * Assists in attaching the tableDrag JavaScript behavior to a themed table. * * Draggable tables should be used wherever an outline or list of sortable items * needs to be arranged by an end-user. Draggable tables are very flexible and * can manipulate the value of form elements placed within individual columns. * * To set up a table to use drag and drop in place of weight select-lists or in * place of a form that contains parent relationships, the form must be themed * into a table. The table must have an ID attribute set and it * may be set as follows: * @code * $table = [ * '#type' => 'table', * '#header' => $header, * '#rows' => $rows, * '#attributes' => [ * 'id' => 'my-module-table', * ], * ]; * return \Drupal::service('renderer')->render($table); * @endcode * * In the theme function for the form, a special class must be added to each * form element within the same column, "grouping" them together. * * In a situation where a single weight column is being sorted in the table, the * classes could be added like this (in the theme function): * @code * $form['my_elements'][$delta]['weight']['#attributes']['class'] = ['my-elements-weight']; * @endcode * * Each row of the table must also have a class of "draggable" in order to * enable the drag handles: * @code * $row = [...]; * $rows[] = [ * 'data' => $row, * 'class' => ['draggable'], * ]; * @endcode * * When tree relationships are present, the two additional classes * 'tabledrag-leaf' and 'tabledrag-root' can be used to refine the behavior: * - Rows with the 'tabledrag-leaf' class cannot have child rows. * - Rows with the 'tabledrag-root' class cannot be nested under a parent row. * * Calling drupal_attach_tabledrag() would then be written as such: * @code * drupal_attach_tabledrag('my-module-table', [ * 'action' => 'order', * 'relationship' => 'sibling', * 'group' => 'my-elements-weight', * ]; * @endcode * * In a more complex case where there are several groups in one column (such as * the block regions on the admin/structure/block page), a separate subgroup * class must also be added to differentiate the groups. * @code * $form['my_elements'][$region][$delta]['weight']['#attributes']['class'] = ['my-elements-weight', 'my-elements-weight-' . $region]; * @endcode * * The 'group' option is still 'my-element-weight', and the additional * 'subgroup' option will be passed in as 'my-elements-weight-' . $region. This * also means that you'll need to call drupal_attach_tabledrag() once for every * region added. * * @code * foreach ($regions as $region) { * drupal_attach_tabledrag('my-module-table', [ * 'action' => 'order', * 'relationship' => 'sibling', * 'group' => 'my-elements-weight', * 'subgroup' => 'my-elements-weight-' . $region, * ]); * } * @endcode * * In a situation where tree relationships are present, adding multiple * subgroups is not necessary, because the table will contain indentations that * provide enough information about the sibling and parent relationships. See * MenuForm::BuildOverviewForm for an example creating a table * containing parent relationships. * * @param array $element * A form element to attach the tableDrag behavior to. * @param array $options * These options are used to generate JavaScript settings necessary to * configure the tableDrag behavior appropriately for this particular table. * An associative array containing the following keys: * - 'table_id': String containing the target table's id attribute. * If the table does not have an id, one will need to be set, * such as <table id="my-module-table">. * - 'action': String describing the action to be done on the form item. * Either 'match' 'depth', or 'order': * - 'match' is typically used for parent relationships. * - 'order' is typically used to set weights on other form elements with * the same group. * - 'depth' updates the target element with the current indentation. * - 'relationship': String describing where the "action" option * should be performed. Either 'parent', 'sibling', 'group', or 'self': * - 'parent' will only look for fields up the tree. * - 'sibling' will look for fields in the same group in rows above and * below it. * - 'self' affects the dragged row itself. * - 'group' affects the dragged row, plus any children below it (the entire * dragged group). * - 'group': A class name applied on all related form elements for this * action. * - 'subgroup': (optional) If the group has several subgroups within it, this * string should contain the class name identifying fields in the same * subgroup. * - 'source': (optional) If the $action is 'match', this string should * contain the classname identifying what field will be used as the source * value when matching the value in $subgroup. * - 'hidden': (optional) The column containing the field elements may be * entirely hidden from view dynamically when the JavaScript is loaded. Set * to FALSE if the column should not be hidden. * - 'limit': (optional) Limit the maximum amount of parenting in this table. * @deprecated in drupal:11.5.0 and is removed from drupal:13.0.0. Use * \Drupal\Core\Render\Element\Table::attachTabledrag() instead. * * @see https://www.drupal.org/node/3035565 * @see MenuForm::BuildOverviewForm() * @see \Drupal\Core\Render\Element\Table::attachTabledrag() */ function drupal_attach_tabledrag(&$element, array $options): void { // Add default values to elements. $options = $options + [ 'subgroup' => NULL, 'source' => NULL, 'hidden' => TRUE, 'limit' => 0, ]; $group = $options['group']; $tabledrag_id = &drupal_static(__FUNCTION__); $tabledrag_id = (!isset($tabledrag_id)) ? 0 : $tabledrag_id + 1; // If a subgroup or source isn't set, assume it is the same as the group. $target = $options['subgroup'] ?? $group; $source = $options['source'] ?? $target; $element['#attached']['drupalSettings']['tableDrag'][$options['table_id']][$group][$tabledrag_id] = [ 'target' => $target, 'source' => $source, 'relationship' => $options['relationship'], 'action' => $options['action'], 'hidden' => $options['hidden'], 'limit' => $options['limit'], ]; $element['#attached']['library'][] = 'core/drupal.tabledrag'; @trigger_error('drupal_attach_tabledrag() is deprecated in drupal:11.5.0 and is removed from drupal:13.0.0. Use \Drupal\Core\Render\Element\Table::attachTabledrag() instead. See https://www.drupal.org/node/3035565', E_USER_DEPRECATED); Table::attachTabledrag($element, $options); } /** Loading core/lib/Drupal/Core/Render/Element/Table.php +172 −5 Changes for core/lib/Drupal/Core/Render/Element/Table.php: 172 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -111,6 +111,11 @@ #[FormElement('table')] class Table extends FormElementBase { /** * The cache ID used for the tableDrag instance counter. */ protected const string TABLE_DRAG_CACHE_ID = 'tabledrag:instance_counter'; /** * {@inheritdoc} */ Loading @@ -135,9 +140,9 @@ public function getInfo() { ], // Properties for tabledrag support. // The value is a list of arrays that are passed to // drupal_attach_tabledrag(). Table::preRenderTable() prepends the HTML ID // Table::attachTabledrag(). Table::preRenderTable() prepends the HTML ID // of the table to each set of options. // @see drupal_attach_tabledrag() // @see Table::attachTabledrag() '#tabledrag' => [], // Render properties. '#pre_render' => [ Loading Loading @@ -388,7 +393,7 @@ public static function validateTable(&$element, FormStateInterface $form_state, * A structured array containing two sub-levels of elements. Properties * used: * - #tabledrag: The value is a list of $options arrays that are passed to * drupal_attach_tabledrag(). The HTML ID of the table is added to each * Table::attachTabledrag(). The HTML ID of the table is added to each * $options array. * * @return array Loading @@ -396,7 +401,7 @@ public static function validateTable(&$element, FormStateInterface $form_state, * * @see \Drupal\Core\Theme\ThemePreprocess::preprocessTable() * @see \Drupal\Core\Render\AttachmentsResponseProcessorInterface::processAttachments() * @see drupal_attach_tabledrag() * @see \Drupal\Core\Render\Element\Table::attachTabledrag() */ public static function preRenderTable($element) { foreach (Element::children($element) as $first) { Loading Loading @@ -446,13 +451,175 @@ public static function preRenderTable($element) { // If the custom #tabledrag is set and there is an HTML ID, add the table's // HTML ID to the options and attach the behavior. if (!empty($element['#tabledrag']) && isset($element['#attributes']['id'])) { $element['#attributes']['class'][] = 'tabledrag-enabled'; $element['#attributes']['data-drupal-tabledrag'] = $element['#attributes']['id']; foreach ($element['#tabledrag'] as $options) { $options['table_id'] = $element['#attributes']['id']; drupal_attach_tabledrag($element, $options); static::attachTabledrag($element, $options); } } return $element; } /** * Assists in attaching the tableDrag JavaScript behavior to a themed table. * * Draggable tables should be used wherever an outline or list of sortable * items needs to be arranged by an end-user. Draggable tables are very * flexible and can manipulate the value of form elements placed within * individual columns. * * To set up a table to use drag and drop in place of weight select-lists or * in place of a form that contains parent relationships, the form must be * themed into a table. The table must have an ID attribute set and it * maybe set as follows: * @code * $table = [ * '#type' => 'table', * '#header' => $header, * '#rows' => $rows, * '#attributes' => [ * 'id' => 'my-module-table', * ], * ]; * return \Drupal::service('renderer')->render($table); * @endcode * * In the theme function for the form, a special class must be added to each * form element within the same column, "grouping" them together. * * In a situation where a single weight column is being sorted in the table, * the classes could be added like this (in the theme function): * @code * $form['my_elements'][$delta]['weight']['#attributes']['class'] = ['my-elements-weight']; * @endcode * * Each row of the table must also have a class of "draggable" in order to * enable the drag handles: * @code * $row = [...]; * $rows[] = [ * 'data' => $row, * 'class' => ['draggable'], * ]; * @endcode * * When tree relationships are present, the two additional classes * 'tabledrag-leaf' and 'tabledrag-root' can be used to refine the behavior: * - Rows with the 'tabledrag-leaf' class cannot have child rows. * - Rows with the 'tabledrag-root' class cannot be nested under a parent row. * * Calling Table::attachTabledrag() would then be written as such: * @code * Table::attachTabledrag('my-module-table', [ * 'action' => 'order', * 'relationship' => 'sibling', * 'group' => 'my-elements-weight', * ]; * @endcode * * In a more complex case where there are several groups in one column (such * as the block regions on the admin/structure/block page), a separate * subgroup class must also be added to differentiate the groups. * @code * $form['my_elements'][$region][$delta]['weight']['#attributes']['class'] = ['my-elements-weight', 'my-elements-weight-' . $region]; * @endcode * * The 'group' option is still 'my-element-weight', and the additional * 'subgroup' option will be passed in as 'my-elements-weight-' . $region. * This also means that you'll need to call Table::attachTabledrag() once for * every region added. * * @code * foreach ($regions as $region) { * Table::attachTabledrag('my-module-table', [ * 'action' => 'order', * 'relationship' => 'sibling', * 'group' => 'my-elements-weight', * 'subgroup' => 'my-elements-weight-' . $region, * ]); * } * @endcode * * In a situation where tree relationships are present, adding multiple * subgroups is not necessary, because the table will contain indentations * that provide enough information about the sibling and parent relationships. * See MenuForm::BuildOverviewForm for an example creating a table containing * parent relationships. * * @param array $element * A form element to attach the tableDrag behavior to. * @param array $options * These options are used to generate JavaScript settings necessary to * configure the tableDrag behavior appropriately for this particular table. * An associative array containing the following keys: * - 'table_id': String containing the target table's id attribute. If the * table does not have an id, one will need to be set, such as * <table id="my-module-table">. * - 'action': String describing the action to be done on the form item. * Either 'match' 'depth', or 'order': * - 'match' is typically used for parent relationships. * - 'order' is typically used to set weights on other form elements with * the same group. * - 'depth' updates the target element with the current indentation. * - 'relationship': String describing where the "action" option should be * performed. Either 'parent', 'sibling', 'group', or 'self': * - 'parent' will only look for fields up the tree. * - 'sibling' will look for fields in the same group in rows above and * below it. * - 'self' affects the dragged row itself. * - 'group' affects the dragged row, plus any children below it (the * entire dragged group). * - 'group': A class name applied on all related form elements for this * action. * - 'subgroup': (optional) If the group has several subgroups within it, * this string should contain the class name identifying fields in the * same subgroup. * - 'source': (optional) If the $action is 'match', this string should * contain the classname identifying what field will be used as the source * value when matching the value in $subgroup. * - 'hidden': (optional) The column containing the field elements may be * entirely hidden from view dynamically when the JavaScript is loaded. * Set to FALSE if the column should not be hidden. * - 'limit': (optional) Limit the maximum amount of parenting in this * table. * * @see \Drupal\menu_ui\MenuForm::buildOverviewForm() */ public static function attachTabledrag(array &$element, array $options): void { // Add default values to elements. $options += [ 'subgroup' => NULL, 'source' => NULL, 'hidden' => TRUE, 'limit' => 0, ]; $group = $options['group']; // The counter for tableDrag instances is stored in the memory cache // instead of a static property, so it does not bleed across requests in // long-running PHP processes (e.g., FrankenPHP, RoadRunner), where memory // cache bins are reset between requests. $cache = \Drupal::cache('memory'); $cache_item = $cache->get(static::TABLE_DRAG_CACHE_ID); $tabledrag_id = $cache_item ? $cache_item->data + 1 : 0; $cache->set(static::TABLE_DRAG_CACHE_ID, $tabledrag_id); // If a subgroup or source isn't set, assume it is the same as the group. $target = $options['subgroup'] ?? $group; $source = $options['source'] ?? $target; $element['#attached']['drupalSettings']['tableDrag'][$options['table_id']][$group][$tabledrag_id] = [ 'target' => $target, 'source' => $source, 'relationship' => $options['relationship'], 'action' => $options['action'], 'hidden' => $options['hidden'], 'limit' => $options['limit'], ]; $element['#attached']['library'][] = 'core/drupal.tabledrag'; } } core/misc/cspell/dictionary.txt +1 −0 Changes for core/misc/cspell/dictionary.txt: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -197,6 +197,7 @@ fodt fouc fourcol francais franken français fraîche frontpage Loading core/misc/tabledrag.js +4 −1 Changes for core/misc/tabledrag.js: 4 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -47,7 +47,10 @@ } Object.keys(settings.tableDrag || {}).forEach((base) => { initTableDrag($(once('tabledrag', `#${base}`, context)), base); initTableDrag( $(once('tabledrag', `[data-drupal-tabledrag="${base}"]`, context)), base, ); }); }, }; Loading core/modules/field_ui/src/Element/FieldUiTable.php +4 −3 Changes for core/modules/field_ui/src/Element/FieldUiTable.php: 4 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ public function getInfo() { * - #region_callback: A callback that provides the region of the table to * place the row in. * - #tabledrag: The value is a list of $options arrays that are passed to * drupal_attach_tabledrag(). The HTML ID of the table is added to each * Table::attachTabledrag(). The HTML ID of the table is added to each * $options array. * * @return array Loading @@ -42,6 +42,7 @@ public function getInfo() { * * @see \Drupal\Core\Render\RendererInterface::render() * @see \Drupal\Core\Render\Element\Table::preRenderTable() * @see \Drupal\Core\Render\Element\Table::attachTabledrag() */ public static function tablePreRender($elements) { $js_settings = []; Loading Loading @@ -122,7 +123,7 @@ public static function tablePreRender($elements) { if (!empty($elements['#tabledrag']) && isset($elements['#attributes']['id'])) { foreach ($elements['#tabledrag'] as $options) { $options['table_id'] = $elements['#attributes']['id']; drupal_attach_tabledrag($elements, $options); static::attachTabledrag($elements, $options); } } Loading @@ -136,7 +137,7 @@ public static function tablePreRender($elements) { * A structured array containing two sub-levels of elements. Properties * used: * - #tabledrag: The value is a list of $options arrays that are passed to * drupal_attach_tabledrag(). The HTML ID of the table is added to each * Table::attachTabledrag(). The HTML ID of the table is added to each * $options array. * * @return array Loading Loading
core/includes/common.inc +7 −143 Changes for core/includes/common.inc: 7 added lines, 143 removed lines. Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\CacheTagsPurgeInterface; use Drupal\Core\DrupalKernel; use Drupal\Core\Render\Element\Table; /** * @defgroup php_wrappers PHP wrapper functions Loading Loading @@ -127,153 +128,16 @@ function base_path() { /** * Assists in attaching the tableDrag JavaScript behavior to a themed table. * * Draggable tables should be used wherever an outline or list of sortable items * needs to be arranged by an end-user. Draggable tables are very flexible and * can manipulate the value of form elements placed within individual columns. * * To set up a table to use drag and drop in place of weight select-lists or in * place of a form that contains parent relationships, the form must be themed * into a table. The table must have an ID attribute set and it * may be set as follows: * @code * $table = [ * '#type' => 'table', * '#header' => $header, * '#rows' => $rows, * '#attributes' => [ * 'id' => 'my-module-table', * ], * ]; * return \Drupal::service('renderer')->render($table); * @endcode * * In the theme function for the form, a special class must be added to each * form element within the same column, "grouping" them together. * * In a situation where a single weight column is being sorted in the table, the * classes could be added like this (in the theme function): * @code * $form['my_elements'][$delta]['weight']['#attributes']['class'] = ['my-elements-weight']; * @endcode * * Each row of the table must also have a class of "draggable" in order to * enable the drag handles: * @code * $row = [...]; * $rows[] = [ * 'data' => $row, * 'class' => ['draggable'], * ]; * @endcode * * When tree relationships are present, the two additional classes * 'tabledrag-leaf' and 'tabledrag-root' can be used to refine the behavior: * - Rows with the 'tabledrag-leaf' class cannot have child rows. * - Rows with the 'tabledrag-root' class cannot be nested under a parent row. * * Calling drupal_attach_tabledrag() would then be written as such: * @code * drupal_attach_tabledrag('my-module-table', [ * 'action' => 'order', * 'relationship' => 'sibling', * 'group' => 'my-elements-weight', * ]; * @endcode * * In a more complex case where there are several groups in one column (such as * the block regions on the admin/structure/block page), a separate subgroup * class must also be added to differentiate the groups. * @code * $form['my_elements'][$region][$delta]['weight']['#attributes']['class'] = ['my-elements-weight', 'my-elements-weight-' . $region]; * @endcode * * The 'group' option is still 'my-element-weight', and the additional * 'subgroup' option will be passed in as 'my-elements-weight-' . $region. This * also means that you'll need to call drupal_attach_tabledrag() once for every * region added. * * @code * foreach ($regions as $region) { * drupal_attach_tabledrag('my-module-table', [ * 'action' => 'order', * 'relationship' => 'sibling', * 'group' => 'my-elements-weight', * 'subgroup' => 'my-elements-weight-' . $region, * ]); * } * @endcode * * In a situation where tree relationships are present, adding multiple * subgroups is not necessary, because the table will contain indentations that * provide enough information about the sibling and parent relationships. See * MenuForm::BuildOverviewForm for an example creating a table * containing parent relationships. * * @param array $element * A form element to attach the tableDrag behavior to. * @param array $options * These options are used to generate JavaScript settings necessary to * configure the tableDrag behavior appropriately for this particular table. * An associative array containing the following keys: * - 'table_id': String containing the target table's id attribute. * If the table does not have an id, one will need to be set, * such as <table id="my-module-table">. * - 'action': String describing the action to be done on the form item. * Either 'match' 'depth', or 'order': * - 'match' is typically used for parent relationships. * - 'order' is typically used to set weights on other form elements with * the same group. * - 'depth' updates the target element with the current indentation. * - 'relationship': String describing where the "action" option * should be performed. Either 'parent', 'sibling', 'group', or 'self': * - 'parent' will only look for fields up the tree. * - 'sibling' will look for fields in the same group in rows above and * below it. * - 'self' affects the dragged row itself. * - 'group' affects the dragged row, plus any children below it (the entire * dragged group). * - 'group': A class name applied on all related form elements for this * action. * - 'subgroup': (optional) If the group has several subgroups within it, this * string should contain the class name identifying fields in the same * subgroup. * - 'source': (optional) If the $action is 'match', this string should * contain the classname identifying what field will be used as the source * value when matching the value in $subgroup. * - 'hidden': (optional) The column containing the field elements may be * entirely hidden from view dynamically when the JavaScript is loaded. Set * to FALSE if the column should not be hidden. * - 'limit': (optional) Limit the maximum amount of parenting in this table. * @deprecated in drupal:11.5.0 and is removed from drupal:13.0.0. Use * \Drupal\Core\Render\Element\Table::attachTabledrag() instead. * * @see https://www.drupal.org/node/3035565 * @see MenuForm::BuildOverviewForm() * @see \Drupal\Core\Render\Element\Table::attachTabledrag() */ function drupal_attach_tabledrag(&$element, array $options): void { // Add default values to elements. $options = $options + [ 'subgroup' => NULL, 'source' => NULL, 'hidden' => TRUE, 'limit' => 0, ]; $group = $options['group']; $tabledrag_id = &drupal_static(__FUNCTION__); $tabledrag_id = (!isset($tabledrag_id)) ? 0 : $tabledrag_id + 1; // If a subgroup or source isn't set, assume it is the same as the group. $target = $options['subgroup'] ?? $group; $source = $options['source'] ?? $target; $element['#attached']['drupalSettings']['tableDrag'][$options['table_id']][$group][$tabledrag_id] = [ 'target' => $target, 'source' => $source, 'relationship' => $options['relationship'], 'action' => $options['action'], 'hidden' => $options['hidden'], 'limit' => $options['limit'], ]; $element['#attached']['library'][] = 'core/drupal.tabledrag'; @trigger_error('drupal_attach_tabledrag() is deprecated in drupal:11.5.0 and is removed from drupal:13.0.0. Use \Drupal\Core\Render\Element\Table::attachTabledrag() instead. See https://www.drupal.org/node/3035565', E_USER_DEPRECATED); Table::attachTabledrag($element, $options); } /** Loading
core/lib/Drupal/Core/Render/Element/Table.php +172 −5 Changes for core/lib/Drupal/Core/Render/Element/Table.php: 172 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -111,6 +111,11 @@ #[FormElement('table')] class Table extends FormElementBase { /** * The cache ID used for the tableDrag instance counter. */ protected const string TABLE_DRAG_CACHE_ID = 'tabledrag:instance_counter'; /** * {@inheritdoc} */ Loading @@ -135,9 +140,9 @@ public function getInfo() { ], // Properties for tabledrag support. // The value is a list of arrays that are passed to // drupal_attach_tabledrag(). Table::preRenderTable() prepends the HTML ID // Table::attachTabledrag(). Table::preRenderTable() prepends the HTML ID // of the table to each set of options. // @see drupal_attach_tabledrag() // @see Table::attachTabledrag() '#tabledrag' => [], // Render properties. '#pre_render' => [ Loading Loading @@ -388,7 +393,7 @@ public static function validateTable(&$element, FormStateInterface $form_state, * A structured array containing two sub-levels of elements. Properties * used: * - #tabledrag: The value is a list of $options arrays that are passed to * drupal_attach_tabledrag(). The HTML ID of the table is added to each * Table::attachTabledrag(). The HTML ID of the table is added to each * $options array. * * @return array Loading @@ -396,7 +401,7 @@ public static function validateTable(&$element, FormStateInterface $form_state, * * @see \Drupal\Core\Theme\ThemePreprocess::preprocessTable() * @see \Drupal\Core\Render\AttachmentsResponseProcessorInterface::processAttachments() * @see drupal_attach_tabledrag() * @see \Drupal\Core\Render\Element\Table::attachTabledrag() */ public static function preRenderTable($element) { foreach (Element::children($element) as $first) { Loading Loading @@ -446,13 +451,175 @@ public static function preRenderTable($element) { // If the custom #tabledrag is set and there is an HTML ID, add the table's // HTML ID to the options and attach the behavior. if (!empty($element['#tabledrag']) && isset($element['#attributes']['id'])) { $element['#attributes']['class'][] = 'tabledrag-enabled'; $element['#attributes']['data-drupal-tabledrag'] = $element['#attributes']['id']; foreach ($element['#tabledrag'] as $options) { $options['table_id'] = $element['#attributes']['id']; drupal_attach_tabledrag($element, $options); static::attachTabledrag($element, $options); } } return $element; } /** * Assists in attaching the tableDrag JavaScript behavior to a themed table. * * Draggable tables should be used wherever an outline or list of sortable * items needs to be arranged by an end-user. Draggable tables are very * flexible and can manipulate the value of form elements placed within * individual columns. * * To set up a table to use drag and drop in place of weight select-lists or * in place of a form that contains parent relationships, the form must be * themed into a table. The table must have an ID attribute set and it * maybe set as follows: * @code * $table = [ * '#type' => 'table', * '#header' => $header, * '#rows' => $rows, * '#attributes' => [ * 'id' => 'my-module-table', * ], * ]; * return \Drupal::service('renderer')->render($table); * @endcode * * In the theme function for the form, a special class must be added to each * form element within the same column, "grouping" them together. * * In a situation where a single weight column is being sorted in the table, * the classes could be added like this (in the theme function): * @code * $form['my_elements'][$delta]['weight']['#attributes']['class'] = ['my-elements-weight']; * @endcode * * Each row of the table must also have a class of "draggable" in order to * enable the drag handles: * @code * $row = [...]; * $rows[] = [ * 'data' => $row, * 'class' => ['draggable'], * ]; * @endcode * * When tree relationships are present, the two additional classes * 'tabledrag-leaf' and 'tabledrag-root' can be used to refine the behavior: * - Rows with the 'tabledrag-leaf' class cannot have child rows. * - Rows with the 'tabledrag-root' class cannot be nested under a parent row. * * Calling Table::attachTabledrag() would then be written as such: * @code * Table::attachTabledrag('my-module-table', [ * 'action' => 'order', * 'relationship' => 'sibling', * 'group' => 'my-elements-weight', * ]; * @endcode * * In a more complex case where there are several groups in one column (such * as the block regions on the admin/structure/block page), a separate * subgroup class must also be added to differentiate the groups. * @code * $form['my_elements'][$region][$delta]['weight']['#attributes']['class'] = ['my-elements-weight', 'my-elements-weight-' . $region]; * @endcode * * The 'group' option is still 'my-element-weight', and the additional * 'subgroup' option will be passed in as 'my-elements-weight-' . $region. * This also means that you'll need to call Table::attachTabledrag() once for * every region added. * * @code * foreach ($regions as $region) { * Table::attachTabledrag('my-module-table', [ * 'action' => 'order', * 'relationship' => 'sibling', * 'group' => 'my-elements-weight', * 'subgroup' => 'my-elements-weight-' . $region, * ]); * } * @endcode * * In a situation where tree relationships are present, adding multiple * subgroups is not necessary, because the table will contain indentations * that provide enough information about the sibling and parent relationships. * See MenuForm::BuildOverviewForm for an example creating a table containing * parent relationships. * * @param array $element * A form element to attach the tableDrag behavior to. * @param array $options * These options are used to generate JavaScript settings necessary to * configure the tableDrag behavior appropriately for this particular table. * An associative array containing the following keys: * - 'table_id': String containing the target table's id attribute. If the * table does not have an id, one will need to be set, such as * <table id="my-module-table">. * - 'action': String describing the action to be done on the form item. * Either 'match' 'depth', or 'order': * - 'match' is typically used for parent relationships. * - 'order' is typically used to set weights on other form elements with * the same group. * - 'depth' updates the target element with the current indentation. * - 'relationship': String describing where the "action" option should be * performed. Either 'parent', 'sibling', 'group', or 'self': * - 'parent' will only look for fields up the tree. * - 'sibling' will look for fields in the same group in rows above and * below it. * - 'self' affects the dragged row itself. * - 'group' affects the dragged row, plus any children below it (the * entire dragged group). * - 'group': A class name applied on all related form elements for this * action. * - 'subgroup': (optional) If the group has several subgroups within it, * this string should contain the class name identifying fields in the * same subgroup. * - 'source': (optional) If the $action is 'match', this string should * contain the classname identifying what field will be used as the source * value when matching the value in $subgroup. * - 'hidden': (optional) The column containing the field elements may be * entirely hidden from view dynamically when the JavaScript is loaded. * Set to FALSE if the column should not be hidden. * - 'limit': (optional) Limit the maximum amount of parenting in this * table. * * @see \Drupal\menu_ui\MenuForm::buildOverviewForm() */ public static function attachTabledrag(array &$element, array $options): void { // Add default values to elements. $options += [ 'subgroup' => NULL, 'source' => NULL, 'hidden' => TRUE, 'limit' => 0, ]; $group = $options['group']; // The counter for tableDrag instances is stored in the memory cache // instead of a static property, so it does not bleed across requests in // long-running PHP processes (e.g., FrankenPHP, RoadRunner), where memory // cache bins are reset between requests. $cache = \Drupal::cache('memory'); $cache_item = $cache->get(static::TABLE_DRAG_CACHE_ID); $tabledrag_id = $cache_item ? $cache_item->data + 1 : 0; $cache->set(static::TABLE_DRAG_CACHE_ID, $tabledrag_id); // If a subgroup or source isn't set, assume it is the same as the group. $target = $options['subgroup'] ?? $group; $source = $options['source'] ?? $target; $element['#attached']['drupalSettings']['tableDrag'][$options['table_id']][$group][$tabledrag_id] = [ 'target' => $target, 'source' => $source, 'relationship' => $options['relationship'], 'action' => $options['action'], 'hidden' => $options['hidden'], 'limit' => $options['limit'], ]; $element['#attached']['library'][] = 'core/drupal.tabledrag'; } }
core/misc/cspell/dictionary.txt +1 −0 Changes for core/misc/cspell/dictionary.txt: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -197,6 +197,7 @@ fodt fouc fourcol francais franken français fraîche frontpage Loading
core/misc/tabledrag.js +4 −1 Changes for core/misc/tabledrag.js: 4 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -47,7 +47,10 @@ } Object.keys(settings.tableDrag || {}).forEach((base) => { initTableDrag($(once('tabledrag', `#${base}`, context)), base); initTableDrag( $(once('tabledrag', `[data-drupal-tabledrag="${base}"]`, context)), base, ); }); }, }; Loading
core/modules/field_ui/src/Element/FieldUiTable.php +4 −3 Changes for core/modules/field_ui/src/Element/FieldUiTable.php: 4 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ public function getInfo() { * - #region_callback: A callback that provides the region of the table to * place the row in. * - #tabledrag: The value is a list of $options arrays that are passed to * drupal_attach_tabledrag(). The HTML ID of the table is added to each * Table::attachTabledrag(). The HTML ID of the table is added to each * $options array. * * @return array Loading @@ -42,6 +42,7 @@ public function getInfo() { * * @see \Drupal\Core\Render\RendererInterface::render() * @see \Drupal\Core\Render\Element\Table::preRenderTable() * @see \Drupal\Core\Render\Element\Table::attachTabledrag() */ public static function tablePreRender($elements) { $js_settings = []; Loading Loading @@ -122,7 +123,7 @@ public static function tablePreRender($elements) { if (!empty($elements['#tabledrag']) && isset($elements['#attributes']['id'])) { foreach ($elements['#tabledrag'] as $options) { $options['table_id'] = $elements['#attributes']['id']; drupal_attach_tabledrag($elements, $options); static::attachTabledrag($elements, $options); } } Loading @@ -136,7 +137,7 @@ public static function tablePreRender($elements) { * A structured array containing two sub-levels of elements. Properties * used: * - #tabledrag: The value is a list of $options arrays that are passed to * drupal_attach_tabledrag(). The HTML ID of the table is added to each * Table::attachTabledrag(). The HTML ID of the table is added to each * $options array. * * @return array Loading