Event Listeners

Event Listeners

ParOne emits events based on user interactions. These will allow you to respond to those interactions in your application. These events are also available on the ParOne video tag itself.

EventNotes
enterFullscreenEmitted when a user enters fullscreen
exitFullscreenEmitted when a user exits fullscreen
videoEndedEmitted when a video ends

// Add an EventListener

const player = document.querySelector("parone-video-block")
player.addEventListener("videoEnded", () => {
  // do something
})



WebView Events

📣 Special thanks to the Tech team at SwingU for requesting this one!

ParOne’s WebView Events enables partners to build Native first applications with the Enterprise ParOne Video Player and other products.

ParOne emits events based on user interactions. These will allow you to respond to those interactions in your native application. These events are also available on the ParOne video tag itself.

EventNotes
enterFullscreenEmitted when a user enters fullscreen
exitFullscreenEmitted when a user exits fullscreen

Apple iOS

Below is example code for detecting these events. You will want to copy this in the existing component definition.

For additional information see Messaging between WKWebView and Swift | (GitHUB)

import SwiftUI
import WebKit
struct WebView: UIViewControllerRepresentable {
  let htmlString: String

  func makeUIViewController(context: Context) -> WebViewController {
    let viewController = WebViewController()
    viewController.loadHTMLString(htmlString)
    return viewController
  }

  func updateUIViewController(_ uiViewController: WebViewController, context: Context) {
    uiViewController.loadHTMLString(htmlString)
  }
}

class WebViewController: UIViewController {
  private lazy var webView: WKWebView = {
    let webViewConfig = WKWebViewConfiguration()
    webViewConfig.dataDetectorTypes = []
    webViewConfig.allowsInlineMediaPlayback = true
    webViewConfig.mediaTypesRequiringUserActionForPlayback = []

    let webView = WKWebView(frame: .zero, configuration: webViewConfig)
    return webView
  }()

  override func viewDidLoad() {
    super.viewDidLoad()

    view.addSubview(webView)
    webView.translatesAutoresizingMaskIntoConstraints = false

    // add listener for enterFullscreen
    let userCC = webView.configuration.userContentController
    userCC.add(Coordinator(),  name: "enterFullscreen")
    NSLayoutConstraint.activate([
      webView.topAnchor.constraint(equalTo: view.topAnchor),
      webView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
      webView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
      webView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
    ])
  }

  func loadHTMLString(_ htmlString: String) {
    webView.loadHTMLString(htmlString, baseURL: nil)
  }
}
struct ContentView: View {
  let htmlString = "<html><head><meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0'></meta><script src='https://sdk.parone.io/parone.min.js'></script></head><body>This is a video test<br><parone-video-block feed='YOUR_FEED_ID' content-key='CONTENT_KEY'></parone-video-block></html>"

  var body: some View {
    WebView(htmlString: htmlString)
  }
}

class Coordinator: NSObject, WKScriptMessageHandler {

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
      if let name = message.name.components(separatedBy: ".").last {
        print("Received message: \(name)")
      }
    }
}

Android

Below is example code for detecting these events. You will want to copy this in the existing component definition.

For additional information see Messaging between WebView and Android.

private const val arg_id = "id"
private const val arg_feed = "feed"

class JavaScriptInterface {
  // name of the handler must match name of event
    @JavascriptInterface
    public void enterFullscreen() {
        Toast.makeText(WebViewActivity.this, "Respond to enterFullscreen event", Toast.LENGTH_LONG).show();
    }
}

class SingleBlockFragment : Fragment() {
  private var contentKey: String = ""
  private var feed: String = "Unknown"
  private var targetView: FrameLayout? = null
  private var contentView: FrameLayout? = null
  private var customView: View? = null

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    arguments?.let {
      contentKey = it.getInt(arg_id)
      feed = it.getString(arg_feed) ?: "Unknown"
    }
  }

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    contentView = view.findViewById(R.id.mainview);
    targetView = view.findViewById(R.id.targetview);
    val html = """
        <script src='parone.min.js'></script>
        <parone-video-block content-key='$this.contentKey' feed='$this.feed'/>
    """
    val webView = view.findViewById<WebView>(R.id.webview).apply {
      settings.javaScriptEnabled = true
      settings.domStorageEnabled = true
      webChromeClient = object: WebChromeClient() {
        override fun onShowCustomView(view: View, callback: CustomViewCallback) {
            targetView?.addView(view)
            customView = view
            contentView?.setVisibility(View.GONE)
            targetView?.setVisibility(View.VISIBLE)
            targetView?.bringToFront()
        }

        override fun onHideCustomView() {
          customView?.setVisibility(View.GONE)
          targetView?.removeView(customView)
          customView = null
          targetView?.setVisibility(View.GONE)
          contentView?.setVisibility(View.VISIBLE)
        }
      }
      webViewClient = WebViewClient()
    }
    // we expect the interface object to named Android
    webView.addJavascriptInterface(new JavaScriptInterface(), "Android");

    webView.loadDataWithBaseURL(
      "https://sdk.parone.io", html,
      "text/html; charset=UTF-8",
      "UTF-8", ""
    )
  }

  override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
  ): View? {
    return inflater.inflate(R.layout.fragment_single_block, container, false)
  }

  companion object {
    @JvmStatic
    fun newInstance(id: Int = 0, feed: String? = null) =
      SingleBlockFragment().apply {
        arguments = Bundle().apply {
            putInt(arg_id, id)
            putString(arg_feed, feed)
        }
      }
  }
}