Is there a way I can detect when a QWebElement is rendered in a QWebFrame?



  • I implement my web view from QWebView and I would like to find an HTML object in the page being loaded (I use http://qt-project.org/doc/qt-4.8/webkit-domtraversal.html and search for a specific type) and somehow intercept an event or a signal that tells me such WebElement is about to be rendered or it has just been rendered. Is it possible at all?

    Thank you



  • Yes, use "MutationObserver":https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver with

    @CustomObj *jscustom = new CustomObj();
    QObject::connect(jscustom, SIGNAL(customSignal()), this, SLOT(MY_SLOT()));

    ...

    QWebFrame->addToJavaScriptWindowObject(QString("customJScallback"), jscustom);@

    After try evaluate a script like this:

    @QString MutationObserver = "";
    MutationObserver.append("(function () {");
    MutationObserver.append(" var observer = new MutationObserver(function(mutations) {");
    MutationObserver.append(" mutations.forEach(function(mutation) {");
    MutationObserver.append(" if(typeof window.customJScallback === "function") {");

    //call object, object emit signal to customSignal, customSignal call MY_SLOT()
    MutationObserver.append(" window.customJScallback();");

    MutationObserver.append(" } else {");
    MutationObserver.append(" console.log("customJScallback is undefined");");
    MutationObserver.append(" }");
    MutationObserver.append(" }); ");
    MutationObserver.append(" });");
    MutationObserver.append("");
    MutationObserver.append(" observer.observe(document.documentElement, {");
    MutationObserver.append(" attributes: true,");
    MutationObserver.append(" childList: true,");
    MutationObserver.append(" characterData: true");
    MutationObserver.append(" });");
    MutationObserver.append("})();";

    QWebPage->mainFrame()->evaluateJavaScript(MutationObserver);@

    When mutations occur in "DOM" you can intercept them using "MY_SLOT".



  • Hi Guilherme,

    thank you for your answer, I didn't know about the mutation observer, it seems very powerful!
    The object I want to receive a signal from, though, is not a custom object and I have no control over the content of the HTML page.
    I know it's an 'object' tag and I know its mime type (it comes from HbbTV specification, I can give you more details if you want, but I suspect it's not relevant for you) but that's about it.

    Thank you



  • Another thing I noticed when trying the mutation observer (at least on my embedded version of webkit) is that there is no callback when an HTML object is rendered, but only when some of its attributes are changed.



  • bq. but only when some of its attributes are changed.

    But this is fully supported by "MutationObserver", just do this:

    @ QString MutationObserver = "";
    MutationObserver.append("(function () {");
    MutationObserver.append(" var observer = new MutationObserver(function(mutations) {");
    MutationObserver.append(" mutations.forEach(function(mutation) {");
    MutationObserver.append(" if(typeof window.customJScallback === "function") {");

    //call object, object emit signal to customSignal, customSignal call MY_SLOT()
    MutationObserver.append("                if (\"attributes\" === mutation.type) {");
    MutationObserver.append("                   window.customJScallback();");
    MutationObserver.append("                }");
    
    MutationObserver.append("            } else {");
    MutationObserver.append("                console.log("customJScallback is undefined");");
    MutationObserver.append("            }");
    MutationObserver.append("        });    ");
    MutationObserver.append("    });");
    MutationObserver.append("");
    MutationObserver.append("    observer.observe(document.documentElement, {");
    MutationObserver.append("        attributes: true,");
    MutationObserver.append("        childList: true,");
    MutationObserver.append("        characterData: true");
    MutationObserver.append("    });");
    MutationObserver.append("})();";
     
    QWebPage->mainFrame()->evaluateJavaScript(MutationObserver);@
    

    Config MutationObserver with this:

    @// configuration of the observer:
    var config = { attributes: true, childList: true, characterData: true };@

    MutationObserverInit

    MutationObserverInit is an object which can specify the following properties:

    bq. NOTE: At the very least, childList, attributes, or characterData must be set to true. Otherwise, "An invalid or illegal string was specified" error is thrown.

    childList: Set to true if additions and removals of the target node's child elements (including text nodes) are to be observed.

    attributes: Set to true if mutations to target's attributes are to be observed.

    characterData: Set to true if mutations to target's data are to be observed.

    subtree: Set to true if mutations to not just target, but also target's descendants are to be observed.

    attributeOldValue: Set to true if attributes is set to true and target's attribute value before the mutation needs to be recorded.

    characterDataOldValue: Set to true if characterData is set to true and target's data before the mutation needs to be recorded.

    attributeFilter: Set to an array of attribute local names (without namespace) if not all attribute mutations need to be observed.

    Please read of documentation in "MutationObserver":https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

    Good luck!



  • Hi Guilherme,

    this doesn't seem to call the callback when the object is rendered.

    Thank you,
    Sergio



  • Enable developer-tools in QtWebkit:

    @QWebSettings *settings = QWebSettings::globalSettings();
    settings->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);@

    Compile and run your project.

    Click with right-button of "Mouse" in "WebView".

    Go to "Inspect".

    Go to "Console tab" and analysis.



  • Hi Guilherme,

    I appreciate the time you spent to answer, but I don't understand how your comments answer my questions, sorry :)



  • Hi obs_sergio!

    You know what "Developer tools" of webkit?

    Like this: !http://themescompany.com/wp-content/uploads/2011/08/chrome1.jpg(developer tools)!

    There may be a problem in script with "evaluateScript", to analyze the problem you should use the "developertools".

    I wait you try this.



  • Thank you,

    I will give it a try, but it won't be easy on an embedded device (set top box).
    In any case in my previous messages I wanted to say that I think using MutationObserver might be impractical for two reasons:

    • as I said, the object I want to receive a signal from is not a custom object and I have no control over the content of the HTML page.
    • the second point is what I meant by saying "that there is no callback when an HTML object is rendered, but only when some of its attributes are changed", I'd probably explain it better. I have read the documentation and I tried your example (very helpful by the way, I also tried to modify it and play around it a bit), I have the feeling MutationObserver starts working after an HTML object is loaded in the page when some of its attributes are changed runtime. What I needed was a notification when an object with a particular mime type was rendered at any time, i.e. while the page was first rendered AND when its visualisation attributes changed runtime, but the former does not seem possible


  • But the signal of which is specifically?
    I thought you wanted to know the time when there are changes in the "DOM" and at this point you would use "QWebElement" combined with your custom sign, I am sure?

    If not that, it could be more clear on what your "ultimate purpose"?

    Good work!! :)



  • The HTML object looks like the following

    <object type="video/broadcast" id="whatever the author chooses"></object>

    This object is defined by OIPF (Open IP-TV Forum) and is supposed to give control of the audio/video of a broadcast TV channel to a javascript application.

    It has a z-order, but on embedded platforms, the video plane is always at the bottom, there is no way to move it relative to arbitrary graphic objects, therefore the z-order must be simulated somehow.

    Assuming the graphic objects in an HTML page are rendered from bottom (low z-order numbers) to top, if I know when such object is rendered, I can erase (by applying a mask) everything in its rectangle (which has a lower z-order number). Objects that are rendered after such object will remain untouched appearing over it.

    There is no custom sign, I have no control on the id of the object, nor I have control on the HTML page or javascript.



  • I know that there is no custom sign, I referred to the example I posted in my first post:
    @
    CustomObj *jscustom = new CustomObj();
    QObject::connect(jscustom, SIGNAL(customSignal()), this, SLOT(MY_SLOT()));
    ...
    QWebFrame->addToJavaScriptWindowObject(QString("customJScallback"), jscustom);
    @

    Perhaps your question is not clear, or you do not understand my example.



  • I know that there is no custom sign, I referred to the example I posted in my first post:
    @
    CustomObj *jscustom = new CustomObj();
    QObject::connect(jscustom, SIGNAL(customSignal()), this, SLOT(MY_SLOT()));
    ...
    QWebFrame->addToJavaScriptWindowObject(QString("customJScallback"), jscustom);
    @

    Perhaps your question is not clear, or you do not understand my example.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.