Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loosing DOM state when prepending element #200

Open
tropperstyle opened this issue Jul 12, 2020 · 5 comments
Open

Loosing DOM state when prepending element #200

tropperstyle opened this issue Jul 12, 2020 · 5 comments

Comments

@tropperstyle
Copy link

tropperstyle commented Jul 12, 2020

Environment

  • morphdom version: 2.6.1
  • Browser: Safari 13.1.1 / Chrome 83.0.4103.116

Expected behavior

Calling morphdom to prepend a element to the container should keep the previous active input element focus

Actual behavior

The browser state and input focus is lost

Reproduce

I tried adding an ID to every element, even the newly introduced element.

https://jsfiddle.net/kajr2zmv/

All console.log statements expected to be true

"isActive control", true
"isActive appendEl", true
"isActive control", true
"isActive prependEl", false
@tropperstyle
Copy link
Author

FWIW, I originally stumbled across this as my element scroll position was getting lost. The input focus is just a smaller use-case easier to test against

While replacing an existing DOM tree with an entirely new DOM tree will actually be very fast, it comes with a cost. The cost is that all of the internal state associated with the existing DOM nodes (scroll positions, input caret positions, CSS transition states, etc.) will be lost

This is extremely misleading as the morphdom algorithm comes with this same cost. I couldn't find a version without this behavior. It appears to build down to the use of appendChild

@Wildhoney
Copy link

Wildhoney commented Aug 4, 2020

You'll find a lot of the diffing algorithms have the same problem with prepending to the tree.

Curious though if this is on the roadmap to fix?

@snewcomer
Copy link
Collaborator

snewcomer commented Aug 7, 2020

@tropperstyle I'd have to take a deep look at this. As you mentioned, once we detect a change, we throw a grenade at the siblings and children. However, if they exist in cache by id, we stitch them back together. This seems to still lose the focus state.

I'm not sure of a good solution yet. Seems like we would have to keep a cache of focused state around and add that that back to the DOM after we have traversed the tree. Surely something that would be nice for this library to handle. Just not sure of a good solution...

@tropperstyle
Copy link
Author

FWIW, I originally stumbled across this as my element scroll position was getting lost. The input focus is just a smaller use-case easier to test against

So, tracking focus explicitly wouldn't have helped in my case as I discovered this issue after loosing scrollTop. There might be other "stateful" properties I'm not aware of off the top of my head

@leastbad
Copy link

Hey @snewcomer,

I've been trying to find a solution to this problem for several days. It cuts deeper than just focus and scroll state.

We're finding that if you insert a new sibling, two additional problems emerge when you "grenade" siblings.

  1. The onBeforeElUpdated callback is not considered, so any attempts to preserve a sibling (we use at attribute to mark elements as protected from morphing) are silently ignored.
  2. The internal state of an iframe is reloaded due to being detached and reattached from the DOM.

I'm willing to PR this but I feel like I'm a bit under water trying to figure out how to attack this. I've been trying to figure out a way to get siblings enumerated in handleNodeAdded and into the It seems like instead of doing the fromNodesLookup object. I am just breaking it, though, and after three days, I have to send up the white flag.

Is this on your horizon, Scott? Do you have any idea how to best go about implementing this functionality?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants