Iframe-resizer: URL doesn't change in the browser when link clicked in child.

Created on 20 Dec 2016  路  6Comments  路  Source: davidjbradshaw/iframe-resizer

This is carried over from issue #347. I couldn't reopen it because I wasn't the OP so I started this one so you'd see it since that one was closed.

Sorry I didn't get back sooner, I'm still having trouble with this but I'm in the middle of the production migration right now so I've set this aside as a known issue but not a show stopper.

All I need to do is, when I click a link in the child page, I need the parent to navigate to that page so that the URL in the browser changes and can be bookmarked or copied and sent in an email, etc. What is currently happening is that I click on a link in the child page and only the content in the iframe changes but the URL in the browser stays the same.

I did as you suggested and added the messageCallback which sent the correct URL to the parent to navigate to, but if I tell the parent to navigate to that page, both the child and the parent try to navigate to it and it goes into the loop. But if I cancel the navigation in the child, I never get the messageCallback.

I also tried setting the default target to parent in the child frame, but then it shows the entire child page in the browser without the parent.

I'm sure it's something I'm doing wrong, not real familiar with Javascript, but I've tried everything I could google for several days and nothing has worked. I could set up an example and give you access to it if it would help. I'd be willing to pay for your time.

question

Most helpful comment

Based on my answer from #347. You need to have the child post back the new URL to the parent

<script>
  window.iFrameResizer = {
    readyCallback: function(){
      window.parentIFrame.sendMessage({
        path: location.path,
        title: document.title
      });
    }
  }
</script>

Then in the parent use messageCallback to mangle the child URL into what ever format you need to match your backend and use history.pushState() to update the location bar.

iFrameResizer({
  messageCallback: (msg) => history.pushState(null, msg.title, manglePath(msg.path))
})

You then need to handle the user pressing the back button.

window.addEventListener(
  'onpopstate', 
  () => document.getElementById('myIFrame').src = deManglePath(location.path), 
  false
);

Note that you'll need to write your own manglePath() and demanglePath() functions for this to work. Which I guess in your case would be something like this.



function manglePath(path) {
  return 'trac/' + path;
}

function demanglePath(path) {
  return path.replace(/trac\//,'');
}

All 6 comments

So what I think your asking, is that when the content changes in the iFrame, that this is then a bookmarkable page. So you can load the parent page with whatever child page.

That's correct. I have Django running via gunicorn at "/" in Nginx and Trac using tracd running through a reverse proxy at "/trac". I set up an application in Django called "code" and my urls.py to translate anything that comes in as "code" to load the parent Django page with the remaining part of the URL passed to the iframe as https://mywebsite.com/trac/remainingpart. This works really well, in that I can get to any part of the Trac wiki, tickets, timeline, etc., by navigating straight to that URL in the browser. But it doesn't work when I click on a link in the child page. The URL just stays the same.

Based on my answer from #347. You need to have the child post back the new URL to the parent

<script>
  window.iFrameResizer = {
    readyCallback: function(){
      window.parentIFrame.sendMessage({
        path: location.path,
        title: document.title
      });
    }
  }
</script>

Then in the parent use messageCallback to mangle the child URL into what ever format you need to match your backend and use history.pushState() to update the location bar.

iFrameResizer({
  messageCallback: (msg) => history.pushState(null, msg.title, manglePath(msg.path))
})

You then need to handle the user pressing the back button.

window.addEventListener(
  'onpopstate', 
  () => document.getElementById('myIFrame').src = deManglePath(location.path), 
  false
);

Note that you'll need to write your own manglePath() and demanglePath() functions for this to work. Which I guess in your case would be something like this.



function manglePath(path) {
  return 'trac/' + path;
}

function demanglePath(path) {
  return path.replace(/trac\//,'');
}

Thank you! It's working as expected now. In case anyone else has this issue, all I ended up doing was in the child readyCallback function, I added:

window.parentIFrame.sendMessage(location.href);

Then in the parent messageCallback function, I added:

history.replaceState(null, null, messageData.message);

The history.pushState appended the URL to the existing one but replaceState replaced it as needed. For whatever reason, I didn't have to do anything special for the user hitting the back button. However, I'm having a new issue now where if I refresh the page, the child exits the iframe and takes over the whole page. I might be able to fix it with Django/Nginx but if you have any ideas, I'd love to hear them.

Thanks again!

That is why you need the manglePath functions.

Yeah, I can see how that would be helpful in most cases but with the way my reverse proxy is set up, it wasn't giving me the results I needed. I'll figure it out. Thanks again.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sebaplaza picture sebaplaza  路  5Comments

frederic117 picture frederic117  路  4Comments

Fanvaron picture Fanvaron  路  4Comments

premedios picture premedios  路  5Comments

Warox23 picture Warox23  路  6Comments