Listbox HTMLViewer Read Only with Delay

I have a subclass of HTMLViewer that’s attempting to be read-only (see code below). The HTMLViewer loads a URL of an object that lives in a listbox row.

The problem I have is that when the user changes listbox rows too fast. This happens:

  1. The currently selected listbox row calls, LoadMyURL and sets DownloadComplete to False.
  2. The DocumentComplete event from the previously selected listbox row fires, setting DownloadComplete to True.
  3. The CancelLoad event from the currently selected listbox row sees DownloadComplete is True, so it bails out and never loads the current listbox’s object URL.

What’s the proper way to handle this? Thanks

Public Sub LoadMyURL(url as String)

    me.DownloadComplete = False

    me.LoadURL( url )

End Sub

Sub DocumentComplete(URL as String) Handles DocumentComplete
    me.DownloadComplete = True

End Sub

Function CancelLoad(URL as String) Handles CancelLoad as Boolean

    If me.DownloadComplete = True then

    // Don't allow the user to navigate
    return true

    end if

End Function

Perhaps disable the listbox once the user has pressed a row? Then re-enable it once the download is complete. Also perhaps have a timer (say 20 secs) so if the page doesn’t load in that time you can re-enable the listbox and cacel the load.

DocumentComplete passes the URL of the document that is completing; check if it is the currently selected one in the listbox, and if not, ignore the event (don’t set DownloadComplete).

Thanks guys. I went the route of disabling the listbox, since in my testing it seems DocumentComplete could potentially fire multiple times for the same web page. I used @Michel_Bujardet suggestion of using a timer in DownloadComplete here to combat that.

Is there any way to also disable the HTMLViewer? Setting the enabled property doesn’t work. And the problem I see is that as DownladComplete is firing, the user can click on and access the links that have already loaded up.

Use the Canceload event. If you return True, no link will work.

https://documentation.xojo.com/api/deprecated/htmlviewer.html#htmlviewer-cancelLoad

Thanks, but that’s not working for me. See original post.

You may need a CriticalSection on the HtmlViewer. See https://documentation.xojo.com/api/code_execution/criticalsection.html .

Cancelload works like clockwork for me.

You could modify your code as such:

Function CancelLoad(URL as String) Handles CancelLoad as Boolean

System.debuglog CurrentMethodName 'signals CancelLoad has been called

           // Don't allow the user to navigate
    return me.DownloadComplete

End Function

That way you can verify CancelLoad indeed fires when you click a link.

I frankly don’t see how this would not work.

Could you post the HTML source of what you display ?

So I believe my problem is with the period set for the timer I use in the DownloadComplete event.

If the period is too slow (500 milliseconds in testing), it leaves the DownloadComplete property False for too long, allowing the user to get a click in on HTMLViewer.

If the period is too fast (200 milliseconds in testing), it may miss loading something?

Hi Mark, if you don’t want someone to click on the list, stop them from doing it - disable the list box while the HTML loads and enable it again when loaded. But if you really want them to click on the list as and when they like, on app opening you could preload the html for all list items into an array and display the html for the relevant item using HTMLViewer.LoadPage.

I didn’t like the way the listbox felt being disabled, so I added an array to the HTMLViewer control to act as sort of a queue.

When LoadMyURL is called, it adds the URL to the array. The CancelLoad event removes it from the array before sending off the GET request. After the web page is loaded, the DocumentComplete event checks to see if the array is empty. If it is, it sets DownloadComplete to True. In a situation when the DocumentComplete event fires for a previous listbox row, and there is another URL waiting in the array, it will not set DownloadComplete to true. This allows the CancelLoad event to send the current listbox row’s request through.

I’m not sure if I’m foreseeing everything here, but it seems to work consistently.

Sounds good. Well done.