0

I have the following code:

<div class="row">
<div>
    <iframe id="myFrame" name="myFrame" class="btn-block" ng-src="{{myframeSrc | trusted}}" onLoad="contentChanged()" scrolling="no"></iframe>
</div>

<script type="text/javascript">
var contentChanged = function() {
    alert('frame content has changed');
};
</script>

I know this is supposed to work (and it does), as the alert does popup. However, I'm getting an [Uncaught ReferenceError: contentChanged is not defined] error. What am I doing wrong? Note: I'm loading the src thru Angular, but needed plain javascript to detect frame source changing when a link is clicked outside of Angular inside the iFrame.

Artvader
  • 906
  • 2
  • 15
  • 31
  • I should mention that the above is being loaded as a TemplateUrl in an Angular directive, if that helps. And I get the error no matter where I put the script. – Artvader Jun 24 '16 at 03:49
  • UPDATE: I put the script immediately above the closing tag and isolated it from other scripts I'm using and the error is gone. – Artvader Jun 24 '16 at 03:55

4 Answers4

2

Your code snippet is absolutely right. Only mistake is the way you declared and its due to JavaScript Variable hoisting.

Your code should be like below.

<script type="text/javascript">
function contentChanged() {
    alert('frame content has changed');
};
</script>

<div class="row">
<div>
    <iframe id="myFrame" name="myFrame" class="btn-block" src="http://www.w3schools.com" onLoad="contentChanged()" height="400"></iframe>
  
</div>

The difference is in your function is only defined when that line is reached, whereas above function is defined as soon as its surrounding function or script is executed, due to hoisting.

Refer to this Simple Example - http://www.w3schools.com/js/js_hoisting.asp

Venkat.R
  • 7,420
  • 5
  • 42
  • 63
  • Your solution did not work on its own, but did give me an idea to solve my problem, so I'm going to mark this as the correct answer. – Artvader Jun 24 '16 at 03:58
  • strange, the working example is there in the question. it works for me. – Venkat.R Jun 24 '16 at 04:01
  • @Artvader This is no different than guest271314 's answer, which was posted first... Note that variable hoisting does not cross ` – user193130 Jun 24 '16 at 04:01
1

Try substituting function declaration for var statement which calls anonymous function. See var functionName = function() {} vs function functionName() {}, What's the difference in those declarations (in JavaScript)?

<script type="text/javascript">
function contentChanged() {
    alert('frame content has changed');
};
</script>
<div class="row">
<div>
    <iframe id="myFrame" name="myFrame" class="btn-block" ng-src="{{myframeSrc | trusted}}" onLoad="contentChanged()" scrolling="no"></iframe>
</div>
Community
  • 1
  • 1
guest271314
  • 1
  • 15
  • 104
  • 177
1

My guess is that since the <iframe> comes before the <script>, it is loaded before the <script>.

Later on, the <script> is loaded and angular finally loads and updates the <iframe>'s src attribute, which causes the <iframe> to reload and run the code in your onLoad again.

To confirm this theory, try this:

<div class="row">
<div>
    <iframe id="myFrame" name="myFrame" class="btn-block" ng-src="{{myframeSrc | trusted}}" onLoad="console.log('iframe loaded'); contentChanged()" scrolling="no"></iframe>
</div>

<script type="text/javascript">
console.log('script tag is being executed');
var contentChanged = function() {
    console.log('contentChanged() is being executed');
    alert('frame content has changed');
};
</script>

You should probably see output in this order in your console (you may have other lines in between from angular or your other code):

iframe loaded

[Uncaught ReferenceError: contentChanged is not defined]

script tag is being executed

iframe loaded

contentChanged() is being executed

Community
  • 1
  • 1
user193130
  • 8,009
  • 4
  • 36
  • 64
  • Actually, no. Even if I put the script in the , I'm still getting the error. – Artvader Jun 24 '16 at 03:48
  • @Artvader Did you try the `console.log()` statements? They should at least give some clue on the behavior. It would be helpful if you update your question with the results. Also, does it say where the ReferenceError is occuring? – user193130 Jun 24 '16 at 03:50
  • I did. And it does as you say. But I put the script above the – Artvader Jun 24 '16 at 03:53
  • @Artvader Does any other piece of code reference `contentChanged`, other than the `onLoad` you've shown here? Also, did you try putting it as the **FIRST** – user193130 Jun 24 '16 at 03:57
  • I was wrapping it in some other function before that waits for document ready, but I isolated the script and put it in the portion and it seems to solve the problem. Thanks! – Artvader Jun 24 '16 at 04:00
  • @Artvader Great, glad it helped. Note that `function() {}` declarations do not need to be wrapped in a document ready since they are never executed until they are called. Not wrapping them actually declares them sooner (and avoids accidentally hiding them form the global scope). However, the code which calls the function *should* be wrapped in a document ready if possible, or you'll get the error you see where the call was made before the function was declared. – user193130 Jun 24 '16 at 04:13
0

window.frames -allows to access iframe window objects directly.

frames.onload = function() {
    alert('frame content has changed')
 };

http://codepen.io/nagasai/pen/jrybgN

Another option is by document.getElementsByTagName onload document.getElementsByTagName('iframe')[0].onload = function() { alert('frame content has changed') };

Codepen:http://codepen.io/nagasai/pen/gMgaJd

Naga Sai A
  • 10,771
  • 1
  • 21
  • 40