2

Background:

Since updating to the 2.9.4 I've begun switching a (nastily hacked in) pygtk version of webkit to the new html2 webview that comes with wxPython.

Question:

From what I can see from the docs (http://wxpython.org/Phoenix/docs/html/html2.WebView.html#html2-webview) there is no way (using python) to detect when a link is being hovered over (such as the "hovering-over-link" event http://webkitgtk.org/reference/webkitgtk/stable/webkitgtk-webkitwebview.html#WebKitWebView-hovering-over-link).

Am I going to have to resort to some javascript hackery to do this or is there another, better, solution?

Ross
  • 206
  • 1
  • 6

3 Answers3

4

So until this gets added I've just gone with the javascript solution. To do this we use javascript to create a page change event which is vetoed in the python code.

First, each time a page is loaded we run the following javascript (using RunScript)

    function hoverLink(link) { 
        window.location.href = "PROXY/HOVER_EVENT_START/" + link;
    }
    function hoverLinkEnd(link) { 
        window.location.href = "PROXY/HOVER_EVENT_END/" + link;
    }

    function setupHoverLinks(elem) { 
        elem.onmouseover = function() {
            hoverLink(elem.href);
        }
        elem.onmouseout = function() {
            hoverLinkEnd(elem.href);
        }
    }

    // Loop through all links in the document and
    // setup some event listeners.
    links = document.getElementsByTagName("a");

    for (var i = 0; i < links.length; i++) {
            link = links[i].href;
            setupHoverLinks(links[i]);
    }

This will cause a page change event each time a mouse in/out event occurs on any of the pages links. The final part of the url contains the relevant link.

We then hook into the EVT_WEB_VIEW_NAVIGATING event, catch any of our custom page changes and veto the page change event, e.g.

def OnPageNavigation(self, evt):
    ...
    uri = evt.GetURL() # you may need to deal with unicode here

    if "PROXY/HOVER_EVENT_START/" in uri:
        # Simple way to get the link
        link = uri.split("PROXY/HOVER_EVENT_START/")[1]
        ...
        # Run your mouseover code
        ...
        evt.Veto()
        return
    elif "PROXY/HOVER_EVENT_END/" in uri:
        ...
        # Run your mouseout code
        ...
        evt.Veto()
        return
    ...
Ross
  • 206
  • 1
  • 6
  • This was really useful, thank you. One thing I would note is that there is a typo on this and a few other example pages floating around, the event is `EVT_WEBVIEW_NAVIGATING` not `EVT_WEB_VIEW_NAVIGATING`. You will get the following error if you include that middle underscore: `AttributeError: 'module' object has no attribute 'EVT_WEB_VIEW_NAVIGATING'` (or at least, I do!) – Alex Bowyer Mar 23 '18 at 18:12
3

It should be possible to get it added. Add a ticket for it at trac.wxwidgets.org.

RobinDunn
  • 6,116
  • 1
  • 15
  • 14
1

The solution given by Ross was working until I got a local .html file ungracefully hijacked by IE8: res://ieframe.dll/dnserrordiagoff_webOC.htm#file:///

Yes, I'm on Windows 7 x64. The error happened with IE11 first but after unsuccessfully searching for a solution, I decided to uninstall it and reset IE8 to its default settings (including moving back its temp folder). To my dismay, that didn't work.

Then I got the idea to prefix the "PROXY/..." string with a valid URI like "127.0.0.1". Not enough, though. But I finally got it to work by adding a port: "127.0.0.1:80". Since this URI is often used by local servers, you can use another value, such as "127.0.0.3:87". Tested with wx 3.0.2 and python 2.7.13.

So, in the javascript part (the python part remains the same), I replaced "PROXY/HOVER_EVENT_START/" with "127.0.0.3:87/PROXY/HOVER_EVENT_START/" and "PROXY/HOVER_EVENT_END/" with "127.0.0.3:87/PROXY/HOVER_EVENT_END/". Et voilà.

Hyperlinks are the raison d'être of the Internet and HTML. Why the wx.html2 API doesn't provide easy ways to handle them, that's a mystery to me.

papin
  • 61
  • 4