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

[DRAFT] Add twoPass option for additional state retention #72

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

botandrose
Copy link

Add Two-Pass option for retaining additional element state

Superseeds #61. Read that for more context, but the gist of it is that this is a stop-gap solution for retaining more element state within morphs until moveBefore lands in browsers.

This draft PR is just an initial spike, so there are some missing pieces that I'd like to resolve before considering this ready for merge:

  1. Only works with morphStyle: innerHTML
  2. moveBefore support is still missing
  3. Only tested in a super basic scenario where it successfully maintains checkbox indeterminate state

What else? Any other thoughts about this direction?

callbacks: mergedConfig.callbacks,
head: mergedConfig.head
}
}

function createPantry() {
const pantry = document.createElement("div");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add style='display:none' to hide?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also maybe throw an id on it? idiomorph-pantry?

Copy link
Author

@botandrose botandrose Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add style='display:none' to hide?

IDK, el.hidden = true on the next line seems to be a higher level way to express the same thing as style="display: none", and is just as good in terms of browser support https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/hidden#browser_compatibility

I'm not married to it, though. If you prefer the latter that's fine.

Copy link
Author

@botandrose botandrose Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also maybe throw an id on it? idiomorph-pantry?

I actually had this at first, but ultimately decided to remove it, thinking that it could get weird with id collision if we have more than one instance of Idiomorph running on a page simultaneously, which seems plausible when used in the context of Turbo or htmx. I'm not imagining it buying us much, either, aside from perhaps someone being able to pick it out more easily in the dev tools html inspector while debugging. What do you think?

src/idiomorph.js Outdated
ctx.callbacks.afterNodeRemoved(tempNode);
}

function moveToPantry(node, ctx) {
if (!node) return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than a recursive algo, do a query selector on [id] to grab all elements that have ids?

might be better for perf

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, except is it possible to do bottom-up in that way? Maybe that's where the idSets can come into the picture?

src/idiomorph.js Outdated
Array.from(ctx.pantry.children).forEach(element => {
const matchElement = root.findElementById(element.id);
if (matchElement) {
matchElement.before(element);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks reasonable, want to also have a moveBefore() branch

maybe we empty the children out of the old node when it is stuck in the pantry?

src/idiomorph.js Outdated Show resolved Hide resolved
src/idiomorph.js Outdated Show resolved Hide resolved
@botandrose
Copy link
Author

Okay, got something working with testing moveBefore. Ideally it'd just be a separate browser run in the main CI job, but it was surprisingly difficult to get a browser with the chrome://flags/#atomic-move experiment enabled. You can't enable it at runtime, the browser needs to boot up with that flag already enabled for it work. But there's no command-line flag to do so! The only way I could figure out how to do this was to dig into the on-disk Chrome profile and manually munge in the setting. So its currently a separate npm script: npm run test-move-before, and this is run as a separate job in the GitHub Actions CI.

Anyways, I've just pushed with it failing so that the next commit will correct a trivial error, so that we can see it passing, thus demonstrating that it is indeed testing what we think it is testing.

@botandrose
Copy link
Author

Just pushed a commit that makes isSoftMatch more strict, in that it no longer considers two elements with differing ids to be a soft match. This was a source of lost or incorrect hidden state during morphs.

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

Successfully merging this pull request may close these issues.

4 participants