diff --git a/js/layout-paragraphs-widget.js b/js/layout-paragraphs-widget.js index a1f336e4d91ad600b1f7bcf1a630caf817d73225..6b9398eb9c087ee752fd21c02bce3b417b4c3df4 100644 --- a/js/layout-paragraphs-widget.js +++ b/js/layout-paragraphs-widget.js @@ -425,10 +425,6 @@ const { $layoutItem } = e.data; const $widget = $layoutItem.closest(".layout-paragraphs-field"); const widgetSettings = $widget.data("widgetSettings"); - const maxDepth = widgetSettings.maxDepth; - // Todo: respect max depth nesting settings for keyboard interactions. - - $widget.find(".layout-paragraphs-moving-message").remove(); let dir; switch (e.keyCode) { case 37: @@ -450,18 +446,13 @@ updateWidget($widget); return false; } - $(".layout-paragraphs-spacer", $widget).remove(); - const $spacer = $("<div>").addClass([ - "layout-paragraphs-spacer", - "js-hidden" - ]); - // Add spacers inside each region. - $(".layout-paragraphs-layout-region", $widget).each((index, elem) => { - $(elem)[dir === "up" ? "append" : "prepend"]($spacer.clone()); - }); + + // Remove the "move" notice. + $widget.find(".layout-paragraphs-moving-message").remove(); + // Build a list of all possible positions. const allPositions = $( - ".layout-paragraphs-item, .layout-paragraphs-spacer", + ".layout-paragraphs-item, .layout-paragraphs-layout-region, .layout-paragraphs-spacer, .layout-paragraphs-disabled-items__items", $widget ) .toArray() @@ -470,58 +461,69 @@ return false; } return true; - }) - .reduce((p, c, i, a) => { - if (i > 0) { - // Previous position was deeper than current position, - // so we need a spacer. - if ( - $(a[i - 1]).parents(".layout-paragraphs-layout").length > - $(c).parents(".layout-paragraphs-layout").length && - $(c).hasClass("layout-paragraphs-layout") - ) { - p.push( - $(c) - .before($spacer.clone().addClass("deeper")) - .prev()[0] - ); - } - } - if ( - c === $layoutItem[0] || - !$(c).hasClass("layout-paragraphs-layout") - ) { - p.push(c); - } - return p; - }, []); + }); - //console.log(allPositions); // Get the position (index) of the current item we are moving. const pos = allPositions.findIndex(el => el === $layoutItem[0]); - // Slice the positions based on the direction. We only need from the current position to beginning or end. - const positions = allPositions.slice( - dir === "up" ? 0 : pos + 1, - dir === "up" ? pos : allPositions.length - ); - while (positions.length) { - const $next = dir === "up" ? $(positions.pop()) : $(positions.shift()); + // Loop through all possible positons, attempting to move to the next in line. + // If a move if not valid, we continue looping until we reach a valid move. + for ( + let i = pos + (dir === "up" ? -1 : 1); + allPositions[i] !== undefined; + i += dir === "up" ? -1 : 1 + ) { + const $next = $(allPositions[i]); + let method; let valid = true; + if ($next.hasClass("layout-paragraphs-layout-region")) { + // Moving into a region. + if (dir === "up" && $layoutItem.parent()[0] === $next[0]) { + // If we are moving up and at the top of a region, we need to + // break out to the next position up the chain. + valid = false; + } + method = dir === "up" ? "append" : "prepend"; + } else if ($next.hasClass("layout-paragraphs-layout")) { + // Moving into a layout. + if (dir === "down" && $layoutItem.parent()[0] === $next.parent()[0]) { + // When moving down, we need to prevent skipping an entire layout + // and instead move ahead into the first avialable region inside the layout. + valid = false; + } else { + method = "before"; + } + } else if ( + $next.hasClass("layout-paragraphs-item") && + $next.parent()[0] === $layoutItem.parent()[0] + ) { + // Moving forward or backward ahead or before a sibling item. + method = dir === "up" ? "before" : "after"; + } else if ($next.hasClass("layout-paragraphs-item")) { + // Moving out of one region and either before or after a paragraph item. + method = dir === "up" ? "after" : "before"; + } else if ($next.hasClass("layout-paragraphs-spacer")) { + // There is a spacer at the very end of the list. + // If the spacer is next, we always insert before it. + method = "before"; + } else if ($next.hasClass("layout-paragraphs-disabled-items__items")) { + method = "append"; + } + // Check for compliance with widget settings. if ( widgetSettings.requireLayouts && $layoutItem.hasClass("layout-paragraphs-layout") === false && $next.closest(".layout-paragraphs-layout-region").length === 0 ) { - //valid = false; + valid = false; } if ( widgetSettings.maxDepth > $next.parents(".layout-paragraphs-layout-region").length ) { - //valid = false; + valid = false; } if (valid) { - $next[dir === "up" ? "before" : "after"]($layoutItem); + $next[method]($layoutItem); return false; } } @@ -542,6 +544,10 @@ $widget.find(".layout-controls, .layout-paragraphs-actions").hide(); $item.addClass("is-moving"); $widget.addClass("is-moving"); + $( + ".active-items, .layout-paragraphs-disabled-items__items", + $widget + ).append($("<div>").addClass(["layout-paragraphs-spacer", "js-hidden"])); $(document).bind("keydown", { $layoutItem: $item }, move); return false; }