How to write a tooltip decorator in RactiveJS

March 14, 2016

After reading this article you will:

  • know how to write a tooltip decorator
  • know how to use decorators in RactiveJS templates
  • have a basic knowledge about writing own decorators

This article is based on example that you could find in RactiveJS documentation.

What is decorator?

Let’s just quote official RactiveJS docs:

“A decorator is a simple way to add behaviour to a node when it is rendered, or to augment it in some way. Decorators are a good way to teach Ractive tricks from other libraries, such as jQuery UI.”

Step by step instruction

Tooltip

First, let’s write a function that will return us position on screen:

var getOffset = function(el) {
  var _x = 0;
  var _y = 0;
  try {
    while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
      _x += el.offsetLeft - el.scrollLeft;
      _y += el.offsetTop - el.scrollTop;
      el = el.offsetParent;
    }

  } catch (e) {
    console.error(e);
  }
  return {
    top: _y,
    left: _x
  };
}

Now let’s write our tooltip function.

First we’ll set variables and we get ID of element which we want to make our tooltip and make him invisible on start.

var tooltip, handlers, eventName;

tooltip = document.getElementById(tooltipId);
tooltip.style.display = 'none';
tooltip.style.position = 'absolute';

Next, we have to write handlers for mouse interaction.

handlers = {
  mouseover: function() {
    tooltip = document.getElementById(tooltipId);
    tooltip.style.display = 'block';
  },

  mousemove: function(event) {
    var parentOffset = getOffset(event.currentTarget);
    tooltip.style.left = parentOffset.left + 'px';
    tooltip.style.top = parentOffset.top - tooltip.getBoundingClientRect().height + 'px';
  },

  mouseleave: function() {
    tooltip.style.display = 'none'
  }
};

These handlers simply sets visibility of tooltip and sets its dimensions.

Next code iterates over above object and adds event handlers.

for (eventName in handlers) {
  if (handlers.hasOwnProperty(eventName)) {
    node.addEventListener(eventName, handlers[eventName], false);
  }
}

Our function returns a teardown function which simply removes all event handlers we set earlier.

return {
  teardown: function() {
    for (eventName in handlers) {
      if (handlers.hasOwnProperty(eventName)) {
        node.removeEventListener(eventName, handlers[eventName], false);
      }
    }
  }
}

After this function we’ll add a global decorator for RactiveJS:

Ractive.decorators.tooltip = tooltipDecorator;

In above example tooltip would be the name which we will be using in templates.

Template

This template should be easy to understand and straightforward.

<script id='tpl' type='text/ractive'>
    <h1>Tooltip decorator</h1>
    <p>This text contains <span decorator='tooltip:one'>tooltips</span>.</p>
    <div id="one" class='ractive-tooltip'>A tooltip is a piece of helper text that appears when you mouseover a particular element</div>
</script>

To add a ractive decorator to template we have to decorator attribute to element. Next we type name of decorator, which in our case is tooltip and ID of HTML element which would work as our tooltip. In this example we use simple text. You can use almost anything.

So, we should use decorator in this form: decorator=‘nameOfDecorator:IdOfElement’. In our example it is decorator='tooltip:one'

CSS

CSS part is available in Fiddle on top of this page.

Initialization

All we have to do is create a new Ractive instance and set appropriate output element and template.

ractive = new Ractive({
    el: 'container',
    template: '#tpl'
});
Kuba Wyrobek Founder, Meteor Developer
Grzegorz Oleksy Junior Meteor Developer