davidjbradshaw / iframe-resizer

Keep iFrames sized to their content.
https://iframe-resizer.com
Other
6.68k stars 983 forks source link

Positioning dialog elements inside iframe #260

Closed pomartel closed 9 years ago

pomartel commented 9 years ago

Working with libraries such as Jquery UI Dialogs or SweetAlert, centering dialogs inside the iframe is a big issue since absolute positioning does not work.

@davidjbradshaw You mentioned that to work around this issue you need to write a bunch of JS and this is pretty much true in my experience. https://github.com/davidjbradshaw/iframe-resizer/issues/83#issuecomment-52031521

Facebook helps you deal with these issues with a positioning API you can call to get the scroll position inside the iframe relative to the parent when building canvas apps (apps living inside an iframe on facebook.com). https://developers.facebook.com/docs/reference/javascript/FB.Canvas.getPageInfo

I was wondering if a positioning API would be feasible for iframe-resizer. If I can get the offset from the the parent frame and the height of the child iframe, then it should be pretty straightforward to position things in the iframe.

Thanks for your consideration and great work on iframe-resizer.

davidjbradshaw commented 9 years ago

Interesting idea, should be pretty simple to implement the same API. I'll have a look next time I have some free time, or happy to take a pull request if you want to do it.

davidjbradshaw commented 9 years ago

That said I still think your better off having SweetAlert in the parentPage and then sending the content to it via parentIFrame.sendMessage(). This is simpler now than when I wrote the comment in #83.

pomartel commented 9 years ago

Thanks for the quick answer David. I am using iframe-resizer so that anybody can add an iframe widget to their website. I don't own the parent iframe (other than asking users to add a snippet of code to their page). Otherwise your solution would have worked. I will check if it would be complicated for me to submit a pull request. I'm not such a great JS developer so we'll see!

pomartel commented 9 years ago

Well it looks like @joschi127 might have solved the problem already! https://github.com/joschi127/iframe-scroll-position

I will take a look at it tomorrow and close the ticket if it does the job.

davidjbradshaw commented 9 years ago

Interesting, not seen that before. It was written for v2. Simpler to do that in v3, as it includes posting messages from the parent to the iFrame. It could also be simplified by using initCallback, instead of the jQuery search on the iFrame.

I'm thinking the best solution would be to have a method on the parentIFrame object that when you give it a callback function, it tells the parent page to start sending position info until you tell it to stop.

hedleysmith commented 7 years ago

Anyone interested in implementing something like iframe-scroll-position but without the jQuery dependency, here's what I came up with:

In the parent window:

ready(function () {
  var iframe = document.getElementById("partialDashboard");
      var sendScrollPosition = function () {
          var data = {
            top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0,
            iframeTop: iframe.offsetTop,
          };
          iframe.contentWindow.postMessage("parentScrollPosition:" + JSON.stringify(data), "*");
      };
      iframe.addEventListener('load', sendScrollPosition);
      window.addEventListener('scroll', function() {
        sendScrollPosition();
      });
});

In the iFrame

if (window.parent) {
  window.addEventListener('message', (e) => {
    if (e.data && typeof e.data === 'string' && e.data.indexOf('parentScrollPosition:') === 0) {
      const dataString = e.data.substr((String('parentScrollPosition:')).length);
      const data = JSON.parse(dataString);
      if (data) {
        window.topOffset = data.top - data.iframeTop;
      }
    }
  }, false);
}

I'm using this in a React.js app loaded in an iFrame. I'm using it to calculate the offset for a modal launched using react-portal. Hacky but it works fine for me for the moment.

Probably worth adding a debounce function around the scroll event and as davidjbradshaw said it would be better to build something where code from within an iFrame 'requested' the current scroll position rather than sending a message constantly.

ZowWeb commented 1 year ago

I had a modal opening inside the child. Since the iframe takes up the entire size, the modal didn't show in the center of the parent viewport. So I came up with this solution.

if ('parentIFrame' in window) {
  const modalScrollYPos = modalRef.current.getBoundingClientRect().top
  window.parentIFrame.scrollTo(0, modalScrollYPos)
}