2

I'm using vb.NET but I incorporated a C# example from here using addEventListener and DOMSubtreeModified to watch the entire DOM document:

    Dim script As HtmlElement = Me.Browser.Document.CreateElement("script")
    script.InnerHtml = "function listenToDOM() { document.addEventListener('DOMSubtreeModified', function(e) { window.external.DOMUpdate() }); }"
    Me.Browser.Document.GetElementsByTagName("body")(0).AppendChild(script)
    Me.Browser.Document.InvokeScript("listenToDOM")

...however, I'm trying to sort it out to more specific DIVs. I haven't succeeded on that front yet but the more I read the more it seems I should be using a MutationObserver which I know nothing about, and I especially don't know how to incorporate with a WebBrowser control.

Has anyone managed to do this?

Note: Yes this is WinForms WB and I did already set my BrowserEmulation to IE11 so that shouldn't be a problem.

Update: I attempted an implementation but it's not triggering:

    Dim scriptEl As HtmlElement = Me.Browser.Document.CreateElement("script")
    scriptEl.InnerHtml = "var targetNode = document.querySelector('.div-content');
        
        var Config = {
            attributes: true, 
            childList: true, 
            characterData: true,
            subtree: true
        };

        function (as Observer = new MutationObserver(function (MutationRecords, MutationObserver) { window.external.DivUpdated(); }); 
    
        Observer.observe(targetNode, Config);"

    Me.Browser.Document.GetElementsByTagName("body")(0).AppendChild(scriptEl)
XionTech
  • 41
  • 5
  • MutationObserver is implemented in DOM4, so Internet Explorer 11 (both versions). You need IE11 compatibility mode to initialize the function (as `[Observer] = new MutationObserver(function (MutationRecords, MutationObserver) { ... }); [Observer].observe(target, { ... });`. Try to set the compatibility mode first, applying this: [How can I get the WebBrowser control to show modern contents?](https://stackoverflow.com/a/38514446/7444103). The `DOMSubtreeModified` mutation event is deprecated. – Jimi Jul 05 '20 at 04:49
  • I mean, if you're referring to the WinForms/WPF WebBrowser control. WebView2 is currently (almost) usable, but you'll have to wait until One.Net is complete. – Jimi Jul 05 '20 at 05:02
  • Until your comment, I hadnt read up on 5.0 or the Webview2. Good to note thanks. Unfortunately, I'm not very familiar with scripting to easily apply your code comment but I'll dig into it. Perhaps it's more straightforward than it seems... – XionTech Jul 07 '20 at 05:53

1 Answers1

2

Here's what I came up with. Granted I will develop it more regarding the specific changes that are being caught...

Private Sub AddScript(Code As String)

    Dim script As HtmlElement = Me.Browser.Document.CreateElement("script")
    script.InnerHtml = Code
    Me.Browser.Document.GetElementsByTagName("body")(0).AppendChild(script)

End Sub

Public Sub CreateObserver(theQuery As String)

    Dim ScriptEl As String = "var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            window.external.DIVUpdated(mutation.type);
        });    
    });

    //everything
    var observerConfig = {
        attributes: true,
        subtree: true,
        childList: true, 
        characterData: true 
    };

    var targetNode = document.querySelector('" & theQuery & "');
    observer.observe(targetNode, observerConfig);"

    AddScript(ScriptEl)

End Sub

I have multiple scripts so I made a separate sub for adding each one. And because the DIV isn't loaded right away, I had to append it later (instead of in the DOC loaded event).

So, from my form I run the CreateObserver('QueryForMyDIVClassOrOtherIdentifier') and the observer triggers my .NET function DIVUpdated() with a mutation.type. In my case I'm looking for characterData changes to the contained text.

I still should add an observer.disconnect() but honestly it's not really important since in my case I'm looking to watch it for the life of the session. But I'm thinking if I return the observer object with the CreateObserver function, I could hold the variable with my .net as an Object and then use that when I do want to disconnect().

XionTech
  • 41
  • 5