insertBefore method

  1. @override
  2. @mustCallSuper
Node insertBefore(
  1. Node child,
  2. Node referenceNode
)
override

Implementation

@override
@mustCallSuper
Node insertBefore(Node child, Node referenceNode) {
  if (enableWebFProfileTracking) {
    WebFProfiler.instance.startTrackUICommandStep('Element.insertBefore');
  }
  Node? originalPreviousSibling = referenceNode.previousSibling;
  Node? node = super.insertBefore(child, referenceNode);
  // Update renderStyle tree.
  if (child is Element) {
    child.renderStyle.parent = renderStyle;
  }

  if (isRendererAttachedToSegmentTree) {
    // If afterRenderObject is null, which means insert child at the head of parent.
    RenderBox? afterRenderObject = originalPreviousSibling?.renderer;

    // Only append child renderer when which is not attached.
    if (!child.isRendererAttachedToSegmentTree) {
      // Found the most closed
      if (afterRenderObject == null) {
        Node? ref = originalPreviousSibling?.previousSibling;
        while (ref != null && afterRenderObject == null) {
          afterRenderObject = ref.renderer;
          ref = ref.previousSibling;
        }
      }

      // Remove all element after the new node, when parent is sliver
      // Sliver's children if change sort need relayout
      if (renderStyle.display == CSSDisplay.sliver &&
          referenceNode is Element &&
          referenceNode.renderer != null &&
          referenceNode.isRendererAttachedToSegmentTree) {
        Node? reference = referenceNode;
        while (reference != null) {
          if (reference.isRendererAttachedToSegmentTree && reference is Element) {
            if (reference.renderer != null &&
                reference.renderer!.parent != null &&
                reference.renderer!.parent is RenderSliverRepaintProxy) {
              (renderer as RenderSliverListLayout).remove(reference.renderer!.parent as RenderSliverRepaintProxy);
            }
            reference.unmountRenderObject(deep: true);
          }
          reference = reference.nextSibling;
        }
      }

      // Renderer of referenceNode may not moved to a difference place compared to its original place
      // in the dom tree due to position absolute/fixed.
      // Use the renderPositionPlaceholder to get the same place as dom tree in this case.
      if (afterRenderObject is RenderBoxModel) {
        RenderBox? renderPositionPlaceholder = afterRenderObject.renderPositionPlaceholder;
        if (renderPositionPlaceholder != null) {
          afterRenderObject = renderPositionPlaceholder;
        }
      }

      child.attachTo(this, after: afterRenderObject);
    }
  }

  if (enableWebFProfileTracking) {
    WebFProfiler.instance.finishTrackUICommandStep();
  }

  return node;
}