I’m building a small Mac Application that gets continuously supplied with data via a web socket. After processing each data segment, the data is displayed in a WebView. New data never replaces any data in the WebView instead new data is always appended to the WebView‘s content using DOM manipulations. The code sample below should give you an idea of what I’m doing.
DOMDocument *doc = self.webview.mainFrame.DOMDocument;
DOMHTMLElement *container = (DOMHTMLElement *)[doc createElement:@"div"];
NSString *html = [NSString stringWithFormat:@"... omitted for the sake of brevity ... "];
[container setInnerHTML:html];
[doc.body appendChild:container];
The rendering of the WebView apparently happens asynchronously. Is there a way to tell when the DOM manipulation finished and the content has been drawn? I want to use something like [webview scrollToEndOfDocument:self] to implement auto scrolling. Listening for DOM Events didn’t help since they seem to be triggered when the DOM was modified but before these changes have been rendered. The code I’m using so far is similar to the following
[self.webview.mainFrame.DOMDocument addEventListener:@"DOMSubtreeModified" listener:self useCapture:NO];
in conjunction with
- (void)handleEvent:(DOMEvent *)event
{
[self.webview scrollToEndOfDocument:self];
}
The problem with this code is that the scrolling happens too early. I’m basically always one data segment behind. Can I register for a callback / notification of any kind that is triggered when the content was drawn?
Using timers
Auto scrolling can be implemented using an
NSTimer. The challenge this solution bears is to figure out when to disable the timer to allow manual scrolling. I wasn’t able to do the latter. Anyways, here is the code that enables autoscrolling using a timer:scrollWebView:simply being a method that callsscrollToEndOfDocument:on the web view.Using notifications
Listing to
NSViewFrameDidChangeNotificationemitted by the web view allows to only scroll in the event of frame size changes. These changes occur when new content is added but also when the size of the encapsulating view changes, e.g. the window is resized. My implementation does not distinguish between those two scenarios.Note: It is important that you instruct the content view of the web view’s scroll view – think about this a couple of times and it will start to make sense – to post notifications when its frame size changes because
NSViewinstances do not do this by default. This is accomplished using the first two lines of code in the example above.