hello, I'm trying to use a web-view and have some control over it, how do I make an event listener to fire when the page is loaded? I'm trying to port this JavaFX example: http://www.java2s.com/Code/Java/JavaFX/WebEngineLoadListener.htm
Hi! Your message reminded me that I wanted to add extension lifecycle for web-view because there is a bunch of useful props that are currently missing. If you are in a hurry you can create needed props yourself using fx/make-ext-with-props
(documented in this readme section: https://github.com/cljfx/cljfx#included-extension-lifecycles)
hello, thanks for the pointers, I was able to know when the page loaded using a custom make-ext-with-props
, but the event handler only gets me the prop value, now I want to trigger a javascript exec on the web engine of the web view, how can I access those instances?
current code:
(ns com.wsscode.demos.reveal
(:require [vlaaad.reveal :as reveal]
[vlaaad.reveal.ext :as rx]
[cljfx.api :as fx]
[cljfx.prop :as prop]
[cljfx.mutator :as mutator]
[cljfx.lifecycle :as lifecycle])
(:import (javafx.scene.web WebView)))
(def web-view-with-ext-props
(fx/make-ext-with-props
{:on-load-state-changed
(prop/make
(mutator/property-change-listener #(-> (.getEngine ^WebView %)
(.getLoadWorker)
(.stateProperty)))
lifecycle/change-listener)}))
(comment
(tap>
{:fx/type web-view-with-ext-props
:desc {:fx/type :web-view
:url "<http://localhost:3000/embed.html>"}
:props {:on-load-state-changed
(fn [e]
(tap> ["state changed" e]))}}))
my goal is to be able to do a postMessage
in the browser window after it loads, so I can communicate something to the page
I believe I can achieve it with (-> web-view (.getEngine) (.executeScript "window.postMessage('the-message')"))
tried to use a custom change-listener
, but when I try to do it the view stops working
(def web-view-with-ext-props
(fx/make-ext-with-props
{:on-load-state-changed
(prop/make
(mutator/property-change-listener #(-> (.getEngine ^WebView %)
(.getLoadWorker)
(.stateProperty)))
#(reify ChangeListener
(changed [a b c value]
(tap> [a b c])
(% value))))}))
Hmm, thatβs because the second arg to prop/make
should be something that satisfies lifecycle protocol
you can try lifecycle/scalar
that passes values from description as-is
and then you can use #(reify ChangeListener ...)
in the description
not sure if I understand how to use it, can you send an example snippet?
(def web-view-with-ext-props
(fx/make-ext-with-props
{:on-load-state-changed
(prop/make
(mutator/property-change-listener #(-> (.getEngine ^WebView %)
(.getLoadWorker)
(.stateProperty)))
lifecycle/scalar)}))
{:fx/type web-view-with-ext-props
:desc {:fx/type :web-view
:url "<http://localhost:3000/embed.html>"}
:props {:on-load-state-changed
(reify javafx.beans.value.ChangeListener
(changed [a b c d]
(tap> [a b c d])))}}
cool, thanks!
I got to render some of what I want, but seems like the built-in browser is lacking some features that cytoscape may require, didnt worked (it renders, but the graph itself doesn't work properly), do you know if there is another option for internal web view, some way to use webkit or something?
hmm, I thought javafxβs web view IS webkit
I just found this: https://jxbrowser.support.teamdev.com/support/solutions/articles/9000013137-jxbrowser-vs-javafx-webview
seems like the webkit renderer there is not been updated in a while
https://github.com/openjdk/jfx/blob/jfx15/doc-files/release-notes-15.0.1.md
It seems to be updated regularly. Do you use Java 8 or Java 11?
using Java 11
tried bumping:
org.openjfx/javafx-controls {:mvn/version "15"}
org.openjfx/javafx-base {:mvn/version "15"}
org.openjfx/javafx-graphics {:mvn/version "15"}
org.openjfx/javafx-media {:mvn/version "15"}
org.openjfx/javafx-web {:mvn/version "15"}
but still same results
Aww, that's sad
What's the library you are trying to use from within webview?
Ah, I saw you mentioned cytoscape
There is something about javafx and Java 11, it seems like it's supposed to work?
I guess what you are seeing is about their desktop app, I'm using the JS version of it: https://js.cytoscape.org/
so, seems like I could try to use their Java version, but its a different thing (I'm trying to re-use the views I already made for the web)
I'm trying to take a spin on JxBrowser (which claims to solve the problem by using Chromium instead of webkit)
I'm trying to follow the code from other components, but Im not sure how to do the initialization described here https://jxbrowser-support.teamdev.com/docs/quickstart/hello-world.html#run-the-javafx-example with cljfx, because there is the Browser to control things and BrowserView to render it
is there something already written in cljfx that looks like that so I can try to base my impl on?
I'll try to come up with example once I'm at the keyboard
But I would suggest looking at components in cljfx.fx nses
The idea is that you create one "composite lifecycle" per mutable object, and then use maps to describe the composition of those mutable objects
grr, they require license and I'm too lazy to fill the form
(require '[cljfx.composite :as composite]
'[cljfx.fx.node :as fx.node]
'[cljfx.mutator :as fx.mutator]
'[cljfx.lifecycle :as fx.lifecycle])
(import '[com.teamdev.jxbrowser.browser Browser]
'[com.teamdev.jxbrowser.engine Engine EngineOptions RenderingMode]
'[com.teamdev.jxbrowser.view.javafx BrowserView])
(def browser
(composite/lifecycle
{:props (composite/props Browser
:url [(fx.mutator/setter
(fn [^Browser browser ^String url]
(when url
(.loadUrl (.navigation browser) url))))
fx.lifecycle/scalar])
:args []
:ctor (fn []
(-> (EngineOptions/newBuilder RenderingMode/HARDWARE_ACCELERATED)
.build
Engine/newInstance
.newBrowser))}))
(def browser-view
(composite/lifecycle
{:props (merge
fx.node/props
(composite/props BrowserView
:browser [fx.mutator/forbidden fx.lifecycle/dynamic]))
:args [:browser]
:ctor (fn [^Browser browser]
(BrowserView/newInstance browser))}))
{:fx/type browser-view
:browser {:fx/type browser
:url "<https://github.com/cljfx/cljfx>"}}
here is the snippet, it does not work for me without license, but it might work if you have license π
hehe, thanks, I'll try it out! but a bummer the license thing
its working! very bad its paid... but I learned a lot about cljfx in process, thanks for the help @vlaaad π
awesome!
my pleasure!
is there a way to start a view like this strait from the repl?
(instead of sending the form, and then requesting "view" via the context menu)
Currently β no. I want to make it possible in some way eventually
I have a couple of ideas, yes. Like, having "autoview" behavior that automatically executes "view" action on submitted values, or a special command object, akin to :repl/quit
But instead it shows last submitted value
yeah, maybe a new ns just to deal with ways to interact with reveal, so users could do something like (render-view-in-panel {...})
I just created also my first custom action, pretty easy π
I wrote a blog post with some of the things from this process: https://blog.wsscode.com/extending-reveal/