Is there a way to use event listeners within a WebView? For instance if I have a button in my html, can pressing that button trigger a script in python/grasshopper and output values etc. Still trying to wrap my head around the Eto documentation. I notice some event methods but not sure if any of them are what I need.
A while back I hacked something together that kind of did this: https://github.com/fraguada/TestWebUI
There is a basic html/js app with some buttons and a Rhino plugin with an Eto form using WebView that listens to the DocumentLoading event fired when the WebView is navigating to a different page. Here I exploit that event, cause the html/js never actually navigates to another page (navigation is canceled). There are probably less hacky ways to go about it.
I was trying another hacky solution of trying to trigger changes in Rhino by listening for Document Title changes but I kept having issues with Rhino being triggered twice - your method saved me so many headaches THANK YOU!!! <3
Bumping this as I have a similar problem. I’m using a webview to load Open Street Maps. With open street maps, when you navigate in the map by scrolling or panning, the url is updated to show the some info about the position of the map. Unfortunately, this doesn’t seem to be triggering any of the events available that I hoped it would.
Does anyone know of a way to get this info when the map is interacted with? Right now the closest I can get is to grab the url when I leave the webview control, but I would like something more responsive. Even the mouse events don’t seem to be triggered unless I am doing something wrong.
Yeah that was the one I tried first, but it doesn’t fire during map operations, even though the url changes. I guess there isn’t any actual navigation to a new page, just an update of the url with the new map info, so the event doesn’t get fired.
The way to do this would be to hook into some javascript event then do something like this (in js): window.location = "myprefix:some-event";, and in the DocumentLoading event, check for the prefix, set e.Cancel = true, and do whatever logic you need there in .NET.
Nothing definitive like connecting a button directly to a web action or vice versa but using the .OnNavigatedEvent does one allow to “DoSomething” and you can look at the web URL during that event and do things based on the URL string but that’s not really proper way to do it.
Ah, is there a reason you go for an OnNavigatedEvent rather than an OnDocumentLoadedEvent like @fraguada suggested above? Say, for a slider on a HTML page that I’d like to use in Rhino or Grasshopper.
Because I did hack my way around it a couple hours after and I went with the DocumentLoaded event instead. But I don’t know if it is the “right” way.
No no, it seems to be called every time a page reloads. Say, you have a slider, it’s called every time the slider is moved. I actually sort of hacked something together yesterday.
import clr
clr.AddReference("Eto")
clr.AddReference("Rhino.UI")
from Eto.Forms import WebView, Form, DynamicLayout
from Eto.Drawing import Size, Padding
import Rhino
class GreenScenarioPanel(Form):
def __init__(self):
self.Title = "Green Scenario WebView"
self.ClientSize = Size(800, 600)
# HTML content with the slider input
html = """
<head>
<meta http-equiv='X-UA-Compatible' content='IE=edge' />
<title>Rhino UI</title>
</head>
<body>
<p>Runoff limit
<input type='range' min='0' max='100' value='50' class='slider' id='runoffLimit'>
</p>
<script>
document.getElementById('runoffLimit').addEventListener('input', function() {
let value = document.getElementById('runoffLimit').value;
window.location = 'greenscenario:runofflimit?' + value;
});
</script>
</body>
"""
# Create the WebView control
self.webview = WebView()
self.webview.Size = Size(800, 600)
self.webview.LoadHtml(html)
# Subscribe to the DocumentLoading event to intercept navigation
self.webview.DocumentLoading += self.on_document_loading
# Create a DynamicLayout for the UI
layout = DynamicLayout(DefaultSpacing=Size(5, 5), Padding=Padding(0))
layout.AddSeparateRow(self.webview)
layout.Add(None)
# Set the layout as the content of the form
self.Content = layout
def on_document_loading(self, sender, e):
# Intercept custom scheme (e.g., "greenscenario")
if e.Uri.Scheme == "greenscenario":
e.Cancel = True # Prevent actual navigation
value = e.Uri.Query.strip('?') # Get the value from the query string
self.communicate_with_webview(value)
def communicate_with_webview(self, value):
# Log the slider value to the Rhino command line or output panel
Rhino.RhinoApp.WriteLine("Slider Value: {0}".format(value))
# Show the form
form = GreenScenarioPanel()
form.Show()
It seems to be doing the trick for me. I found somebody working with C# on another forum post, I just tried to convert it to IronPython and it worked.