Popper-core: Tooltip.js: offset is never set (either with "offset" or "modifiers")

Created on 29 Jun 2017  路  8Comments  路  Source: popperjs/popper-core

  • Tooltip.js v1.1.4
  • Popper.js v1.10.6

CodePen demo

https://codepen.io/hekigan/pen/GEyazB/?editors=1011

Steps to reproduce the problem

On the codepen above, you can see that the offset is never set.

{
    ...
    offset: 100,
    popperOptions: {
      modifiers: {
        offset: {
          offset: 200
        }
      }
    }

What is the expected behavior?

The tooltip should have shifted from the target element by 'x' pixels.

What went wrong?

No change whatsoever.

Any other comments?

I looked up in the 'tooltip.js' source code and I could not find where you set the offset and pass it on to 'popper.js'.
I did see that you merge the options object, but after that, it just does not seem to get used.

# BUG 馃悶 low medium

Most helpful comment

+1 Any news on this?

All 8 comments

This is the PR that introduced this feature.

Maybe @vgavro can help?

Actually, an update on the current state of things, I also tried to use 'onCreate/onUpdate' and nothing happens.

I updated the codepen to reflect the 'onCreate'.

Ok, still investigating what is happening.

So far I discovered that after creating your tooltip const tt = new tooltip(...), then, if you don't use the tt.show() method, you do not have yet access to the tt.popperInstance.

IF I force the use of show() like that :

tt = new tooltip(...);
tt.show();
tt.hide();

Then, I do have access to tt.popperInstance and can set something like:

tt.popperInstance.options.onUpdate = function (e) {...};

Far from ideal --actually super dirty-- and a workaround for now.
But that will have to do until popperOptions works.

And just for the context, I need that when I want to let someone set HTML content instead of text.
By default, the HTMLElement that contains the HTML to display in the tooltip is not hidden.
So I have to force that on onCreate.

Sorry for the long comment, but I hope it will help in fixing the issue.

Looks like from first tooltip draft after refactoring to separate component (as seen here https://github.com/FezVrasta/popper.js/commit/0b107ad496562edb6995cb4ad6f9f13c4f84b571) Tooltip.options.offset was planned, but was never implemented. Thanks for finding it out!

@hekigan About passing popperOptions.modifiers.offset.offset - this should be working, but may not be working as you expected? This setting is used by offset modifier, you can check if it's using it with console.log in npm_packages/popper.js/dist/popper.js. You may start from here. See https://github.com/vgavro/popper.js/blob/master/packages/popper/src/modifiers/index.js#L52
Here is example from my code that may help you find out your issue, I needed dynamic offset, so I needed to create another modifier instead of using "offset" option for offset modifier.

      popup.show()

      // NOTE: pass this modifier to popperOptions after this PR
      // https://github.com/FezVrasta/popper.js/pull/316
      // (should be in tooltip.js 1.1.5 release)
      // see https://www.npmjs.com/package/tooltip.js
      popup.popperInstance.modifiers.push({
        name: 'offset',  // not needed in popperOptions
        enabled: true,  //not needed in popperOptions
        order: 801,  // after offset(800), before computeStyle(850)
        fn: (data) => {
          const index = this.popups.indexOf(popup)
          data.offsets.popper.top += index * POPUP_OFFSET
          return data
        },
      })
      popup.popperInstance.modifiers.sort((x, y) => x.order - y.order)  // not needed in PopperOptions

I'll create merge request for Tooltip.options.offset on this week and take a deeper look to offset modifier.

@vgavro Thank you for your reply.
If you change the offset in the codepen above (first comment), there is no effect at all, even using popperOptions.modifiers.offset.offset form.

So I am not really sure about what is happening. I looked up a bit under the hood, but did not have too much time to find out what to fix.

I am building a vue directive on top of your tooltip.js implementation and it is pretty helpful.
When I have more time, I might do my own implementation directly with popper.js, but right now I am really tight time-wise :)

+1 Any news on this?

This is my current workaround for setting offset... This isn't my exact code - I simplified it for this example - so forgive me if it doesn't run. The principle is the same though.

const offset = 10; /* Change offset here */
const _tooltip = new Tooltip(target, {
  placement: 'top',
  popperOptions: {
    onCreate() {
      setSpacing();
    },

    onUpdate() {
      setSpacing();
    },
  },
});

function setSpacing() {
  const popper = _tooltip.popperInstance.popper;
  const marginSide = getOppositeSide(popper.getAttribute('x-placement'));
  const { style } = popper;

  style.marginTop = 0;
  style.marginRight = 0;
  style.marginBottom = 0;
  style.marginLeft = 0;

  popper.style[`margin${capitalize(marginSide)}`] = `${offset}px`;

  _tooltip.popperInstance.state.updateBound();
}

function getOppositeSide(side) {
  let oppositeSide;

  switch (side) {
    case 'top':
      oppositeSide = 'bottom';
      break;
    case 'right':
      oppositeSide = 'left';
      break;
    case 'bottom':
      oppositeSide = 'top';
      break;
    case 'left':
      oppositeSide = 'right';
      break;
  }

  return oppositeSide;
}

function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.substring(1);
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

nainardev picture nainardev  路  3Comments

FezVrasta picture FezVrasta  路  3Comments

Madhu94 picture Madhu94  路  3Comments

kerf007 picture kerf007  路  3Comments

Sawtaytoes picture Sawtaytoes  路  5Comments