Can't access content of another frame in Chrom

2019-02-21 06:34发布

问题:

I have two frames. The pages in both frames come from the same domain (either localhost or a live domain - both using the same protocol).

The first frame needs to access elements of the second frame (xsample) when it's fully loaded and any onload JS functions have completed. But the second frame takes a while to load.

<frameset cols="*,*" rows="*" border="0" framespacing="0">
    <frame src="picker.asp" name="xpicker" frameborder="no" marginwidth="15" marginheight="15">
    <frame src="doc.asp" name="xsample" frameborder="no" marginwidth="15" marginheight="15">
</frameset>

The code below works in IE and Firefox but not in Chrome or Safari, In those parent.xsample is always false

function startWork(){
if(isSurveyLoaded()==false){
    SL=setTimeout("startWork()",1000);
    return;
}
else{
    setTimeout("doMoreWork()",2000);
}
}

function isSurveyLoaded(){
    if(!parent.xsample){
        return false;
    }
    if(!parent.xsample.self.name){
        return false;
    }
    if(parent.xsample.document.readyState!='complete'){
        return false;
    }
    else{
        return true;
    }
}

回答1:

Use parent.frames["xsample"] to access the frame.

Implicit references to named elements on the global object is not standardized.

On a different note, never do setTimeout("doMoreWork(), 1000)" as this forces the VM to use eval to execute the code.
Use setTimeout(doMoreWork, 1000) which is the proper way to do it.



回答2:

I solved it by:
1. Giving the target frame both a name and an id
2. testing for both
3. testing that a variable (finishedLoading) within the target frame was set to true
(code altered to use === instead of == when testing finishedLoading)

function isSurveyLoaded(){
  if(!(parent.frames["xsample"]  || parent.document.getElementById('xsample'))){
    return false;
  }
  else{
    if(parent.frames["xsample"]){
      target=parent.frames["xsample"];
    }
    else{
      target=parent.document.getElementById('xsample');
    }
  }
  if ((target.finishedLoading==='undefined') || (target.finishedLoading===false) ){
    return false;
  }
  else{
    return true;  
  }
}

Now simplified by using

<frame src="doc.asp" onload="frameisloaded(this)" name="xsample" id="xsample" frameborder="no" marginwidth="15" marginheight="15">


回答3:

In Chrome, accessing window.frames[index] gets you a Window object, from which you can access good stuff like the document within that frame's content.

Accessing it by document.getElementById returns only the iframe element itself, with almost no useful attributes for digging further into the DOM.

This bug in not being able to access the Window object by its name using window.frames[name] the way other browsers do should be fixed!



回答4:

To address the anti-frameset comments: Being critical of those who use frames doesn't answer the question. Secondly there are things that frames do better than any other alternative.

So the question shouldn't be, "What self-respecting web developer uses framesets?" It should be: "What self-respecting full featured browser doesn't support them properly?" and one of the answers is obviously Chrome.

They've sprinkled "security flags" around various functions in their interpreter, including those that facilitate the transfer of certain information between pages in different frames. Consequently things like this don't work when run locally:

top.frames[2].document.getElementById(ID)

However when run on the server it will usually work fine.

If you need it to work locally in Chrome you need to use some sort of workaround. You'll have to be creative. In some cases, like when you know the situation variables, you can create an array to handle the various possibilities ( which is a drag when it doesn't need to be that complex otherwise ).