whatwg / html

HTML Standard
https://html.spec.whatwg.org/multipage/
Other
8.03k stars 2.63k forks source link

Reparenting iframes without reloading #5484

Closed josepharhar closed 4 years ago

josepharhar commented 4 years ago

I have heard several requests for the ability to reparent iframes without reloading, including:

Has this been brought up as a spec issue before? I imagine someone must have thought about this before...

Would it make sense to add a method to iframes to reparent them to another element without reloading?

Another potential use case I've heard from React is to reparent elements other than iframes without losing state. An example of this would be to reparent an input element without losing focus and selection. In this case, perhaps we could have a reparenting method for any element?

cc @mfreed7 @tkent-google @sebmarkbage

Lampe2020 commented 1 year ago

@worldpeaceenginelabs You can't convince me to use svelte. I'll try to look into other simulation's code to figure out an alternative solution.
@jryans And it would be nice if iframes could keep their status at least if they're immediately reinserted, like for example calling Element.appendChild(iframesParent); on an element already in the same DOM.
[EDIT]: Now that Windows93 will soon release their Sys42 (which seems to be able to handle iframes) I could see myself using that for my OS simulation.

quartexNOR commented 1 year ago

I have to respectfully ask that something be done with how IFrames behave when moving an IFrame element within the same parent, this is intolerable.

Like others which have commented I am making a desktop designed as a front-end for a NAS system, and like most "web desktops" it operates with fake (div based) windows. These fake windows look and behave like ordinary windows and have a "send to back" and "bring to front" glyph on its borders.

The problem is, that whenever someone clicks on the "send to back" glyph, I have no choice but to remove the window's element from the parent (which is the "desktop" div in this case), and then re-insert it into the same parent at either the beginning or end of the child collection ( insertBefore() | appendChild() ).

We have spent 4 years building our own compiler, IDE and RTL for this project. The project is written in a unique flavor of Object Pascal designed especially for web-development, and the compiler emits highly effective JavaScript. The desktop system is a huge project that will be used both for teaching (schools use our devtools to teach kids to program in object pascal and Javascript side by side), and also as a NAS front-end, ala Synology.

Being able to move an element at least within the same parent (read: no re-parenting of the element, just move it within the child collection where the element is presently located) is something I quite frankly find strange is still lacking in 2023. This has been requested for 17 years (!) on the Mozilla forums.

I strongly urge you to reconsider your position on this. What I would suggest is something that would not require a lot of work, but can be done relatively easily with the code that is already in the browser core. My suggestion is as follows:

Add methods for moving elements within the same parent, which means no re-parenting is needed, and thus does not cause issues with scripting or security.

Candidates on top of my head would be:

  1. Element.swapChildren( int32 child1, int32 child2)
  2. Element.bringToFront()
  3. Element.sendToBack()

(*) The above would not affect z-order, only the position of the element in a parent's child collection. It would not affect security, mutation events or any of the existing infrastructure. And it would save people from having to re-map the zorder for all child elements just to change display order of an item.

Looking at various posts around the internet where people debate the IFrame problem, the above would solve the majority of cases I have seen.

Kind regards Jon-Lennart Aasenden

Anprotaku commented 1 year ago

Anyone found any solution excluding the slot element?

flackr commented 1 year ago

@sophiebits unfortunately that's not an atomic move and will do a remove and then an insert (with all the associated script running bits).

@annevk What are the script running bits that happen after the remove before the insert? Could we eliminate these? Alternately since we know from the single API call that a node is being moved could we give this move semantics and not apply side effects from insertion/removal in the internal operation if the source / destination documents are the same?

dead-claudia commented 1 year ago

@sophiebits unfortunately that's not an atomic move and will do a remove and then an insert (with all the associated script running bits).

@annevk What are the script running bits that happen after the remove before the insert? Could we eliminate these? Alternately since we know from the single API call that a node is being moved could we give this move semantics and not apply side effects from insertion/removal in the internal operation if the source / destination documents are the same?

Legacy mutation events are synchronous. They can observe the difference very easily.

Also, iframes have semantics run when inserted and removed from the live tree, and there's ways to almost-synchronously observe the resulting navigation when the child and parent frames cooperate.

Just to name a couple.

flackr commented 1 year ago

Even if we create a new API, e.g. https://github.com/whatwg/dom/issues/891, we would still have to answer these questions. My hope is that there are reasonable answers for how these should behave.

@annevk What are the script running bits that happen after the remove before the insert? Could we eliminate these? Alternately since we know from the single API call that a node is being moved could we give this move semantics and not apply side effects from insertion/removal in the internal operation if the source / destination documents are the same?

Legacy mutation events are synchronous. They can observe the difference very easily.

How breaking would it be if your event observers ran after the frame was already parented to the new node? This would leave no observable state where the frame was disconnected. Admittedly this would be a pretty big change for synchronous legacy mutation events but per this intent to deprecate they are already fairly low usage - the cases where the difference in timing of the removal during an operation which is immediately readding the node would be some fraction of those cases.

Also, iframes have semantics run when inserted and removed from the live tree, and there's ways to almost-synchronously observe the resulting navigation when the child and parent frames cooperate.

I'd have to familiarize myself with all of these semantics, but I think it may be reasonable to skip most/all of them in the case where it is known to remain in the document. e.g. newParent.appendChild(alreadyAttachedFrame) as in these cases we explicitly don't want to reload the frame or change/lose state. It shouldn't navigate.

dead-claudia commented 1 year ago

How breaking would it be if your event observers ran after the frame was already parented to the new node? This would leave no observable state where the frame was disconnected. Admittedly this would be a pretty big change for synchronous legacy mutation events but per this intent to deprecate they are already fairly low usage - the cases where the difference in timing of the removal during an operation which is immediately readding the node would be some fraction of those cases.

@flackr Thanks for the call out there on usage. I'll take that bit back.

I'd have to familiarize myself with all of these semantics, [...]

To be fair, iframes are literally mentioned in the title of this issue. Animations are another example, though in theory that could be worked around through some very hacky CSS (read: animation-delay) + event glue.

flackr commented 1 year ago

To be fair, iframes are literally mentioned in the title of this issue. Animations are another example, though in theory that could be worked around through some very hacky CSS (read: animation-delay) + event glue.

Right, but what I'm suggesting is that these side effects shouldn't happen when the element is known to be moving to a different position in the same document. It would make sense that animations shouldn't be canceled and restart as well (as long as the style in the new DOM location still resulted in the animation).

AwokeKnowing commented 1 year ago

I'm glad this is still being looked at because it is vital to be able to use iframes for isolation yet move them as needed, for workflows where you transition between two different views but need the content to be unaffected. In particular full screen views vs regular views, and other cases.

anthonyhoegberg commented 9 months ago

What about instead of reparenting or moving iframes etc, we allow the slot element or something like slots to work not only in shadow root but everywhere? So that we can keep an element in its position in the dom tree and we just slot it somewhere else where we want it to be rendered? We will kind of get the same effect but we wont have to move the element anywhere. We just slot it somewhere else.