Get contents of an iframe which has ajax content,

2019-07-18 15:40发布

I have a Greasemonkey script which uses jQuery and detects if a "class" is present in the document.

var damageMessage = $(".mw_error").text();

Thanks to ShankarSangoli he or she gave me the solution to finding the class when the iframe loads with.

$("iframe").load(function(){

   var damageMessage = $(this).contents().find(".mw_error").text();

});

The problem I have now is that some of the links in the iframe load content via ajax so the iframe doesn't refresh and I cant get the new value for the class "mw_error". It was suggested that I use a ajax success callback but I'm unsure how to do this.

Any help on this would be much appreciated :)

1条回答
看我几分像从前
2楼-- · 2019-07-18 16:22

You can listen for ajax calls, but that gets overly complicated, depending on the target pages. The most robust way to get ajax-ified content on a wild page is to poll for it, like so:

function myCode (jNode) {
    //YOUR CODE HERE
    var damageMessage   = jNode.text();
    //...
}

waitForKeyElements (".mw_error", myCode, false, "iframe");

function waitForKeyElements (
    selectorTxt,    /* Required: The jQuery selector string that
                        specifies the desired element(s).
                    */
    actionFunction, /* Required: The code to run when elements are
                        found. It is passed a jNode to the matched
                        element.
                    */
    bWaitOnce,      /* Optional: If false, will continue to scan for
                        new elements even after the first match is
                        found.
                    */
    iframeSelector  /* Optional: If set, identifies the iframe to
                        search.
                    */
)
{
    var targetNodes, btargetsFound;

    if (typeof iframeSelector == "undefined")
        targetNodes     = $(selectorTxt);
    else
        targetNodes     = $(iframeSelector).contents ()
                                           .find (selectorTxt);

    if (targetNodes  &&  targetNodes.length > 0) {
        /*--- Found target node(s).  Go through each and act if they
            are new.
        */
        targetNodes.each ( function () {
            var jThis        = $(this);
            var alreadyFound = jThis.data ('alreadyFound')  ||  false;

            if (!alreadyFound) {
                //--- Call the payload function.
                actionFunction (jThis);
                jThis.data ('alreadyFound', true);
            }
        } );
        btargetsFound   = true;
    }
    else {
        btargetsFound   = false;
    }

    //--- Get the timer-control variable for this selector.
    var controlObj      = waitForKeyElements.controlObj  ||  {};
    var controlKey      = selectorTxt.replace (/[^\w]/g, "_");
    var timeControl     = controlObj [controlKey];

    //--- Now set or clear the timer as appropriate.
    if (btargetsFound  &&  bWaitOnce  &&  timeControl) {
        //--- The only condition where we need to clear the timer.
        clearInterval (timeControl);
        delete controlObj [controlKey]
    }
    else {
        //--- Set a timer, if needed.
        if ( ! timeControl) {
            timeControl = setInterval ( function () {
                    waitForKeyElements (    selectorTxt,
                                            actionFunction,
                                            bWaitOnce,
                                            iframeSelector
                                        );
                },
                500
            );
            controlObj [controlKey] = timeControl;
        }
    }
    waitForKeyElements.controlObj   = controlObj;
}


Beware that Greasemonkey can also run on iFrames, so you may not need to do anything other than know if you're in an iFrame, depending upon the script's purpose.

Conversely, you can get unexpected results if the GM script(s) fire on the iFrame URL when you haven't planned on it.

For example, suppose you had this page at URL_A:

<body>
    <iframe src="URL_B"></iframe>
</body>

And the GM script's // @include directive(s) covered both urls (// @include URL_*, etc.).

Then if the script just had alert ('Script start.');, you would see 2 alerts upon loading the page.

查看更多
登录 后发表回答