0

MouseEvent.target returns an EventTarget instead of a HTMLElement when clicked inside an iframe, in ScalaJs.

src/main/scala/tutorial/webapp/TutorialApp.scala:

package tutorial.webapp

import org.scalajs.dom._
import org.scalajs.dom.raw._
import scala.scalajs.js

object TutorialApp {
  def main(args: Array[String]): Unit = {
    window.document.body.innerHTML = "<p><b>main window</b></p>"

    val iframe = document.createElement("iframe")
    document.body.appendChild(iframe)
    val iframeWindow = iframe.asInstanceOf[HTMLIFrameElement].contentWindow
    iframeWindow.document.body.innerHTML = "<p><b>iframe</b></p>"


    window.document.addEventListener("click", clicked)        
    // this works as expected:
    // clicking on the 'main window' text, produces this console log:
    // - clicked an HTMLElement B
    // - parent is an HTMLParagraphElement P


    iframeWindow.document.addEventListener("click", clicked)  // this doesn't
    // this does not work as expected:
    // clicking on the 'iframe' text, produces this console log:
    // - clicked an EventTarget B
    // - parent is an HTMLElement P
  }

  def clicked(mouseEvent: MouseEvent) {
    mouseEvent.target match {
      case e: HTMLElement => console.log("clicked an HTMLElement", e.asInstanceOf[HTMLElement].tagName)
      case e: EventTarget => console.log("clicked an EventTarget", e.asInstanceOf[HTMLElement].tagName)
    }

    val parent = mouseEvent.target.asInstanceOf[HTMLParagraphElement].parentElement
    parent match {
      case e: HTMLParagraphElement => console.log("parent is an HTMLParagraphElement", e.asInstanceOf[HTMLElement].tagName)
      case e: HTMLElement => console.log("parent is an HTMLElement", e.asInstanceOf[HTMLElement].tagName)
    }
  }
}

index.html

<html>
  <body>
    <!-- Include Scala.js compiled code -->
    <script type="text/javascript" src="./target/scala-2.12/scala-js-tutorial-fastopt.js"></script>
  </body>
</html>

When I click inside the iframe on the <h1>iframe</h1>, I get an EventTarget instead of an HTMLElement. Casting it to HTMLElement works, but e.parentElement is an HTMLElement instead of HTMLParagraphElement. Why and how to solve it?

David Portabella
  • 11,264
  • 22
  • 87
  • 164

1 Answers1

0

Hoping someone will provide a more precise answer, but in the absence of that:

Iframes are typically loaded from other URLs, often from another origin, and their security model reflects that primary use case – the document inside the iframe is quite isolated from the parent document. I'm not quite sure which exact restriction you're hitting though as manually creating iframes like in your example is not very common.

Usually, the Javascript code running inside the iframe needs to be willing to communicate with Javascript code running in the parent window. Currently in your example you only have code running in the parent window, as the iframe itself does not load any scripts.

Depending on your exact use case, there are several ways to achieve this. For example, you could post custom events to the parent window as described in How to communicate between iframe and the parent site?

Iframes can be really annoying if you don't want the isolation that they come with.

Nikita
  • 2,672
  • 1
  • 16
  • 23