diff --git a/js/Plugin/jstree/hm.jstree.js b/js/Plugin/jstree/hm.jstree.js index b5dd9d797ebf1d5eb361c90c174de24385097dc0..957c08927fb833402977c2b2dcdd00b8d31b3f2a 100644 --- a/js/Plugin/jstree/hm.jstree.js +++ b/js/Plugin/jstree/hm.jstree.js @@ -100,7 +100,7 @@ } if (data.position < list.length - 1) { - after = list[data.position + 1]; + after = list[data.position]; } // Update the data on server side. @@ -109,6 +109,7 @@ target: data.position, parent: parent, old_parent: old_parent, + old_position: data.old_position, after: after, before: before }) diff --git a/src/Controller/HmMenuController.php b/src/Controller/HmMenuController.php index f7ad4c237f00d66adebe2cac87de611acd941c73..e1c12489fee9adba3809a45b23b9dbd1e80dc308 100644 --- a/src/Controller/HmMenuController.php +++ b/src/Controller/HmMenuController.php @@ -170,6 +170,7 @@ class HmMenuController extends ControllerBase { return new Response($this->t('Access denied!')); } + $old_position = (int) $request->get('old_position'); $target_position = $request->get('target'); $parent = $request->get('parent'); $updated_links = $request->get('keys'); @@ -220,7 +221,7 @@ class HmMenuController extends ControllerBase { } } - $new_hierarchy = $this->hmPluginTypeManager->updateHierarchy($target_position, $all_siblings, $updated_links); + $new_hierarchy = $this->hmPluginTypeManager->updateHierarchy($target_position, $all_siblings, $updated_links, $old_position); foreach ($updated_links as $id) { if (!isset($links_uuid[$id])) { $entity = $this->entityTypeManager->getStorage('menu_link_content')->load($id); diff --git a/src/Controller/HmTaxonomyController.php b/src/Controller/HmTaxonomyController.php index 97d56109ed733d01b7c59b7f90de6f373bb4bf73..d7478a4d5b7f8c4d19b8e323b69d1dab5365997c 100644 --- a/src/Controller/HmTaxonomyController.php +++ b/src/Controller/HmTaxonomyController.php @@ -166,6 +166,7 @@ class HmTaxonomyController extends ControllerBase { } $target_position = $request->get('target'); + $old_position = (int) $request->get('old_position'); $old_parent_id = $request->get('old_parent'); // Remove the parent index from the parent id. $old_parent_id = explode('_', $old_parent_id)[0]; @@ -199,7 +200,7 @@ class HmTaxonomyController extends ControllerBase { } } - $new_hierarchy = $this->hmPluginTypeManager->updateHierarchy($target_position, $all_siblings, $updated_terms); + $new_hierarchy = $this->hmPluginTypeManager->updateHierarchy($target_position, $all_siblings, $updated_terms, $old_position); $tids = array_keys($new_hierarchy); // Load all terms needed to update. diff --git a/src/PluginTypeManager.php b/src/PluginTypeManager.php index 9ededb1fc8dc41477b793258dbd8d52c076ebfad..aed468c511f742854837be95412ba1c64fe000d7 100644 --- a/src/PluginTypeManager.php +++ b/src/PluginTypeManager.php @@ -111,78 +111,96 @@ class PluginTypeManager { * All siblings of the new items in an array[$item_id => (int)$weight] * @param array $updated_items * IDs of new items inserted. - * @param int|bool $after - * Indicator if new items are inserted after target position. - * @param int $weight - * The initial weight. + * @param int $old_position + * The old position of moving items. * * @return array * All siblings needed to move and their new weights. */ - public function updateHierarchy(int $target_position, array $all_siblings, array $updated_items, $after = true, int $weight = 0) { + public function updateHierarchy(int $target_position, array $all_siblings, array $updated_items, int $old_position) { $new_hierarchy = []; if (!empty($all_siblings)) { $total = count($all_siblings); $num_new = count(array_diff($updated_items, array_keys($all_siblings))); - // If there is new child, - // the insert position should move backward. - $insert_position = $target_position - $num_new; if ($target_position <= 0) { // The insert postion is the first position. // we don't need to move any siblings. $weight = reset($all_siblings) - 1; } - elseif ($insert_position >= $total - 1) { + elseif ($target_position >= $total - 1) { // The insert postion is the end, // we don't need to move any siblings. $last_item= array_slice($all_siblings, -1, 1, TRUE); $weight = reset($last_item) + 1; } else { - $target_item = array_slice($all_siblings, $insert_position, 2); - $pre_weight = $target_item[0]; - $next_weight = $target_item[1]; - $weight = $pre_weight + 1; + $target_item = array_slice($all_siblings, $target_position, 1); + $weight = $target_item[0]; $total_insert = count($updated_items); + // Figure out if the target element should move forward. + if ($num_new || ($old_position > $target_position)) { + $move_forward = true; + } + else { + $move_forward = false; + } - if ($next_weight - $pre_weight <= $total_insert) { - // The gap is not big enough. - // Need to make some room. - // If the target position is in the second half, - // we will move all siblings - // after the target position forward. - // Otherwise, we will move siblings - // before the target position backwards. - if ($insert_position >= $total / 2) { - $moving_siblings = array_slice($all_siblings, $insert_position + 1, NULL, TRUE); - $after = true; - $expected_weight = $next_weight + 1 + $total_insert; + // If the target position is in the second half, + // we will move all siblings + // after the target position forward. + // Otherwise, we will move siblings + // before the target position backwards. + if ($target_position - $num_new >= $total / 2) { + if ($move_forward) { + $moving_siblings = array_slice($all_siblings, $target_position, NULL, TRUE); + $weight = $target_item[0]; + } + else { + $moving_siblings = array_slice($all_siblings, $target_position + 1, NULL, TRUE); + $weight = $target_item[0] + 1; + } + $after = true; + $expected_weight = $weight + $total_insert; + } + // Move the first bundle. + else { + if ($move_forward) { + $moving_siblings = array_slice($all_siblings, 0, $target_position, TRUE); + $weight = $target_item[0] - 1; } else { - $moving_siblings = array_slice($all_siblings, 0, $insert_position + 1, TRUE); - $after = false; - $weight = $next_weight - 1; - $expected_weight = $pre_weight - count($moving_siblings); + $moving_siblings = array_slice($all_siblings, 0, $target_position + 1, TRUE); + $weight = $target_item[0]; } + $after = false; + $expected_weight = $weight - count($moving_siblings) - $total_insert + 1; + } - // Move all siblings that need to move. - foreach($moving_siblings as $item_id => $item_weight) { - // Skip all links in the updated array. They will be moved later. - if (in_array($item_id, $updated_items)) { - continue; - } - if ($after) { - if ($item_weight < $expected_weight) { - $new_hierarchy[$item_id] = $expected_weight++; - } + // Move all siblings that need to move. + foreach($moving_siblings as $item_id => $item_weight) { + // Skip all items that are in the updated array. + // They will be moved later. + if (in_array($item_id, $updated_items)) { + continue; + } + if ($after) { + if ($item_weight < $expected_weight) { + $new_hierarchy[$item_id] = $expected_weight; } else { - if ($item_weight > $expected_weight) { - $new_hierarchy[$item_id] = $expected_weight++; - } + // The weight is bigger than expected. + // No need to move the rest of siblings. + break; + } + } + else { + if ($item_weight > $expected_weight) { + $new_hierarchy[$item_id] = $expected_weight; } } + // Move to next sibling. + $expected_weight++; } } }