繁体   English   中英

镜子<details>和复选框 state 跨 iframe</details>

[英]mirror <details> and checkbox state across iframe

我有一个 iFrame 可以在其内部加载其父页面。 因此,同一页面的两个副本; iFrame 中的一个,一个不是。

我正在尝试在主页和 iFrame 之间镜像<input type="checkbox"> checked/unchecked<details> open/closed的 state。

我已经解决了每个部分(请参阅问题的// comments ),触发click事件:

对于复选框,我有

let boxes = document.querySelectorAll('input[type="checkbox"]');

for (let box of boxes)) {
    myIFrame.getElementById(box.id).checked = box.checked; // works
    if (inIFrame) {parent.getElementById(box.id).checked = document.getElementById(box.id).checked; // doesn't work
}

(上面的条件inIFrame只是测试检查页面是否加载到 iFrame 中的简写)

而对于<details>

let detailEls = document.querySelectorAll('details');

for (let i = 0; i < detailEls.length; i++) {
  myIFrame.querySelectorAll('details')[i].open = querySelectorAll('details')[i].open; // works, but 1-click behind
  }

但奇怪的是,这滞后了一个点击。 所以如果我点击,点击,点击打开主页上的详细信息A,B,C,只有A,B会在iFrame中打开——下一次点击,Z0D61F8370CAD1D412F80B84D143E12会打开。

如果不清楚,这是我的问题的摘要:

  1. 为什么<details> state 滞后? 这似乎与复选框的策略相同,但结果不同。
  2. 为什么勾选的 state 只从主页镜像到 iFrame,反之不行?

谢谢!

这是一个演示您想要的行为的复制品,通常遵循您的模式:

https://stackblitz.com/edit/so-mirror-iframe?file=lib/script.js

没有完整的代码很难说,但这里有一些需要考虑的事情:

  1. 如果您在详细信息上使用click事件,那可能会给您带来“滞后”行为。 事实证明,对于详细信息, click事件发生open属性更新之前。 当您的同步器运行时,您刚刚单击的那个总是读入错误的 state。

    • 改用toggle事件,在更新open属性触发。
  2. 假设它不是第一个代码块中的错字, parent是对父window的引用,而不是它的document

    • 请改用parent.document.getElementById

好的,您使用的逻辑将无法按照您的意愿mirror vice-versa ,所以我将在WINDOW 和 IFRAMEclick基础上进行

这是我的回复,这是一个链接(请在新标签中打开)

这是概念:

  • 我制作了想要在iframewindow 上mirrored的元素的window These arrays are made in the same way so that the keys/indexes each relate to their equivalent in the separate window( window.boxes[0] is the first box in window and childWindow.boxes[0] is the first box in iframe )
  • 现在最重要的部分是您将在addEventListener块中看到的async部分。 你会看到我await一个 promise 的timeout ,持续0 ms ,但是像这样的异步函数是如何工作的,它会等到它没有阻塞任何东西,然后 RUN 这就是为什么它忽略了detail栏给出的滞后效应

window.html

<html><h2>WINDOW</h2>
<iframe id="iframe" width="500" height="300" src="/"></iframe>

<details>.</details>
<details>..</details>
<details>...</details>
<details>....</details>
<details>.....</details>
<input type="checkbox">Hm</input>
<input type="checkbox">Hmm</input>
<input type="checkbox">Hmmm</input>
<input type="checkbox">Hmmmm</input>
<input type="checkbox">Hmmmmm</input>

<script>(async()=>{
window.iframe=document.getElementById('iframe') //iframe
window.childWindow=iframe.contentWindow //window to iframe
window.waitFinish=async function(){ //needful waiting
  await new Promise(r=>setTimeout(r,0))
}

window.boxes = [...document.querySelectorAll('input[type="checkbox"]')] //checkboxes
window.details = [...document.querySelectorAll('details')] //details

//wait for iframe to finish loading(if you're doing this manually by the time you begin it'd be finished loading so no worries)
await new Promise(r=>{
  let s=setInterval(()=>{
    if(typeof childWindow.details=="object"){
      clearInterval(s); return r(1)
    }
  },0)
})

//window to iframe
boxes.forEach((box,index)=>{
  box.addEventListener("click",async(ev)=>{
    await waitFinish()
    childWindow.boxes[index].checked=box.checked
  })
})
details.forEach((detail,index)=>{
  detail.addEventListener("click",async(ev)=>{
    await waitFinish()
    childWindow.details[index].open=detail.open
  })
})

//iframe to window
childWindow.boxes.forEach((box,index)=>{
  box.addEventListener("click",async(ev)=>{
    await waitFinish()
    window.boxes[index].checked=box.checked
  })
})
childWindow.details.forEach((detail,index)=>{
  detail.addEventListener("click",async(ev)=>{
    await waitFinish()
    window.details[index].open=detail.open
  })
})
})()</script>
</html>

iframe.html

<html><h2>IFRAME</h2>
<i><a target="_blank" href="https://iframe-mirror.paultaylor2.repl.co">Full Page</a></i>

<details>.</details>
<details>..</details>
<details>...</details>
<details>....</details>
<details>.....</details>
<input type="checkbox">Hm</input>
<input type="checkbox">Hmm</input>
<input type="checkbox">Hmmm</input>
<input type="checkbox">Hmmmm</input>
<input type="checkbox">Hmmmmm</input>

<script>
window.boxes = [...document.querySelectorAll('input[type="checkbox"]')] //checkboxes
window.details = [...document.querySelectorAll('details')] //details
</script>
</html>

你犯了一个小错误。 你的代码是:

for (let box of querySelectorAll('input[type="checkbox"]')) {
    myIFrame.getElementById(box.id).checked = box.checked; // works
    if (inIFrame) {parent.getElementById(box.id).checked = getElementById(box.id).checked; // doesn't work
}

什么时候需要

for (let box of querySelectorAll('input[type="checkbox"]')) {
    myIFrame.getElementById(box.id).checked = box.checked; // works
    if (inIFrame) {parent.getElementById(box.id).checked = document.getElementById(box.id).checked; // works now that it's fixed
}

您忘记了document object 作为父级。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM