Uploaded image for project: 'Fluid Infusion'
  1. Fluid Infusion
  2. FLUID-6394

The Orator's selectionReader control does not factor in margins for placement




      When determining its placement, the selection reader does not factor in the margin of its container. This can cause it to shift quite widely as seen in https://issues.gpii.net/browse/GPII-3767


      The above was fixed with PR ( https://github.com/fluid-project/infusion/pull/960 ); however, in doing so it broke the Orator's demo.

      Steps to reproduce:

      1. Open the Orator demo
      2. Select some text 

      Notice that the play button is displayed far from the selection.


      It seems that just factoring in the margins was an overly simplistic understanding of the issue. The Orator demo also has a margin but accounting for it, actually causes the play button to appear far away. It may in fact be related to the container that either the content and/or the play button is located in. For example, the CSS position style directive may play a part. 

      Modifying the fluid.orator.selectionReader.calculatePostion like below has some success, but still cannot account for all cases. 

      In the code example below we find the parent's position either using jQuery's offset or position functions. We use these to find the position of the element relative to the document. The DOMrect's provide positioning based on the viewport. So we use the parent's DOMRect to compare against the selection's DOMRect and attempt to use this to determine where the selection in in relation to the document position as found using the jQuery methods. We then use this to pass along CSS top and left properties to absolutely position the button. However, I've had mixed results when there is absolute and relative positioning in the Orator demo vs through UIO+ on the https://morphic.world website. The position still isn't accurate across both cases.

          fluid.orator.selectionReader.calculatePosition = function (range, fontSize, offsetScale) {
              var edgeOffset = fontSize * (fluid.get(offsetScale, "edge") || 1);
              var pointerOffset = parseFloat($("html").css("font-size")) * 1.8;
              var rangeRect = range.getBoundingClientRect();
              var parent = range.startContainer.parentElement;
              var parentRect = parent.getBoundingClientRect();
              var isPositioned = $(parent).offsetParent().css("position") !== "static";
              var parentPosition = isPositioned ? $(parent).offset() : $(parent).position();        var position = {
                  top: (parentPosition.top - parentRect.top) || - parseFloat($(parent).css("font-size")),
                  left: parentPosition.left + (rangeRect.left - parentRect.left)
              };        if (rangeRect.top < edgeOffset) {
                  position.top = position.top + rangeRect.bottom + pointerOffset;
                  position.location = fluid.orator.selectionReader.location.BOTTOM;
              } else {
                  position.top = position.top + rangeRect.top - pointerOffset;
                  position.location = fluid.orator.selectionReader.location.TOP;
              }        return position;


        1. orator demo issue.png
          55 kB
          Justin Obara
        2. screenshot.png
          45 kB
          Justin Obara

          Issue Links



              jobara Justin Obara
              jobara Justin Obara
              0 Vote for this issue
              2 Start watching this issue