usablica / intro.js

Lightweight, user-friendly onboarding tour library
http://introjs.com
Other
22.8k stars 2.59k forks source link

Simple update to _getOffset for working with iframe elements #480

Closed arjshiv closed 3 years ago

arjshiv commented 8 years ago

Use case Using IntroJS on elements within iframes from the main page

Issue It is possible to highlight elements within an iframe using IntroJs, however, when the iframe is offset from the main window, the helperLayer and tooltipReferenceLayer are positioned incorrectly.

Fix This can be very easily accommodated within IntroJS by a small enhancement to the _getOffset() function

Code before change

  function _getOffset(element) {
    var elementPosition = {};

    //set width
    elementPosition.width = element.offsetWidth;

    //set height
    elementPosition.height = element.offsetHeight;

    //calculate element top and left
    var _x = 0;
    var _y = 0;
    while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) {
      _x += element.offsetLeft;
      _y += element.offsetTop;
      element = element.offsetParent;
    }
    //set top
    elementPosition.top = _y;
    //set left
    elementPosition.left = _x;

    return elementPosition;
  }

Code after change

function _getOffset(element) {
    var elementPosition = {};
    //iframe workaround - dummy client rect here
    var boundingFrameClientRect = {
          top: 0,
          left: 0
    };
    if ((element) && (element.ownerDocument !== window.document)) { //lives in iframe
          boundingFrameClientRect = element.ownerDocument.defaultView.frameElement.getBoundingClientRect()
    }
    //set width
    elementPosition.width = element.offsetWidth;
    //set height
    elementPosition.height = element.offsetHeight;
    //calculate element top and left
    var _x = 0;
    var _y = 0;
    while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) {
          _x += element.offsetLeft;
          _y += element.offsetTop;
          element = element.offsetParent;
    }
    //set top
    elementPosition.top = _y + boundingFrameClientRect.top;     //account for elements within a frame
    //set left
    elementPosition.left = _x + boundingFrameClientRect.left;     //account for elements within a frame

    return elementPosition;
}

If this is fine, I will go ahead and submit a pull request. This is completely backwards compatible and should not impact any existing use cases.

sundysd commented 8 years ago

it would be very useful if we could support this!!

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.