Fork me on GitHub
#cljfx
<
2020-12-10
>
wilkerlucio03:12:54

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

vlaaad08:12:06

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)

wilkerlucio13:12:44

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?

wilkerlucio13:12:46

current code:

wilkerlucio13:12:48

(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     ""}
     :props   {:on-load-state-changed
               (fn [e]
                 (tap> ["state changed" e]))}}))

wilkerlucio13:12:27

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

wilkerlucio13:12:38

I believe I can achieve it with (-> web-view (.getEngine) (.executeScript "window.postMessage('the-message')"))

wilkerlucio13:12:28

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))))}))

vlaaad14:12:30

Hmm, that’s because the second arg to prop/make should be something that satisfies lifecycle protocol

vlaaad14:12:00

you can try lifecycle/scalar that passes values from description as-is

vlaaad14:12:31

and then you can use #(reify ChangeListener ...) in the description

wilkerlucio14:12:55

not sure if I understand how to use it, can you send an example snippet?

vlaaad14:12:05

(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     ""}
 :props   {:on-load-state-changed
           (reify javafx.beans.value.ChangeListener
             (changed [a b c d]
               (tap> [a b c d])))}}

wilkerlucio14:12:06

cool, thanks!

wilkerlucio14:12:21

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?

vlaaad14:12:54

hmm, I thought javafx’s web view IS webkit

wilkerlucio14:12:51

seems like the webkit renderer there is not been updated in a while

vlaaad15:12:16

It seems to be updated regularly. Do you use Java 8 or Java 11?

wilkerlucio16:12:37

using Java 11

wilkerlucio16:12:22

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"}

wilkerlucio16:12:24

but still same results

vlaaad16:12:37

Aww, that's sad

vlaaad16:12:51

What's the library you are trying to use from within webview?

vlaaad17:12:55

Ah, I saw you mentioned cytoscape

vlaaad17:12:45

There is something about javafx and Java 11, it seems like it's supposed to work?

wilkerlucio17:12:00

I guess what you are seeing is about their desktop app, I'm using the JS version of it: https://js.cytoscape.org/

wilkerlucio17:12:36

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)

wilkerlucio17:12:05

I'm trying to take a spin on JxBrowser (which claims to solve the problem by using Chromium instead of webkit)

wilkerlucio17:12:15

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

wilkerlucio17:12:04

is there something already written in cljfx that looks like that so I can try to base my impl on?

vlaaad18:12:17

I'll try to come up with example once I'm at the keyboard

🙏 3
vlaaad18:12:44

But I would suggest looking at components in cljfx.fx nses

vlaaad18:12:49

The idea is that you create one "composite lifecycle" per mutable object, and then use maps to describe the composition of those mutable objects

vlaaad20:12:53

grr, they require license and I'm too lazy to fill the form

vlaaad20:12:56

(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 ""}}

vlaaad20:12:22

here is the snippet, it does not work for me without license, but it might work if you have license 😄

wilkerlucio21:12:39

hehe, thanks, I'll try it out! but a bummer the license thing

wilkerlucio21:12:30

its working! very bad its paid... but I learned a lot about cljfx in process, thanks for the help @U47G49KHQ 🙏

vlaaad22:12:57

my pleasure!

wilkerlucio22:12:06

is there a way to start a view like this strait from the repl?

wilkerlucio23:12:11

(instead of sending the form, and then requesting "view" via the context menu)

vlaaad06:12:22

Currently — no. I want to make it possible in some way eventually

vlaaad07:12:33

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

vlaaad07:12:40

But instead it shows last submitted value

wilkerlucio07:12:42

yeah, maybe a new ns just to deal with ways to interact with reveal, so users could do something like (render-view-in-panel {...})

wilkerlucio07:12:34

I just created also my first custom action, pretty easy 🙂

👍 3
wilkerlucio20:12:21

I wrote a blog post with some of the things from this process: https://blog.wsscode.com/extending-reveal/