[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/webroot/rsrc/js/core/ -> ToolTip.js (source)

   1  /**
   2   * @requires javelin-install
   3   *           javelin-util
   4   *           javelin-dom
   5   *           javelin-vector
   6   * @provides phabricator-tooltip
   7   * @javelin
   8   */
   9  
  10  JX.install('Tooltip', {
  11  
  12    statics : {
  13      _node : null,
  14  
  15      show : function(root, scale, align, content) {
  16        if (__DEV__) {
  17          switch (align) {
  18            case 'N':
  19            case 'E':
  20            case 'S':
  21            case 'W':
  22              break;
  23            default:
  24              JX.$E(
  25                "Only alignments 'N' (north), 'E' (east), 'S' (south), " +
  26                "and 'W' (west) are supported."
  27              );
  28              break;
  29          }
  30        }
  31  
  32        var node_inner = JX.$N(
  33          'div',
  34          { className: 'jx-tooltip-inner' },
  35          [
  36            JX.$N('div', { className: 'jx-tooltip' }, content),
  37            JX.$N('div', { className: 'jx-tooltip-anchor' })
  38          ]);
  39  
  40        var node = JX.$N(
  41          'div',
  42          { className: 'jx-tooltip-container' },
  43          node_inner);
  44  
  45        node.style.maxWidth  = scale + 'px';
  46  
  47        JX.Tooltip.hide();
  48        this._node = node;
  49  
  50        // Append the tip to the document, but offscreen, so we can measure it.
  51        node.style.left = '-10000px';
  52        document.body.appendChild(node);
  53  
  54        // Jump through some hoops trying to auto-position the tooltip
  55        var pos = this._getSmartPosition(align, root, node);
  56        pos.setPos(node);
  57      },
  58  
  59      _getSmartPosition: function (align, root, node) {
  60        var pos = JX.Tooltip._proposePosition(align, root, node);
  61  
  62        // If toolip is offscreen, try to be clever
  63        if (!JX.Tooltip.isOnScreen(pos, node)) {
  64          align = JX.Tooltip._getImprovedOrientation(pos, node);
  65          pos = JX.Tooltip._proposePosition(align, root, node);
  66        }
  67  
  68        JX.Tooltip._setAnchor(align);
  69        return pos;
  70      },
  71  
  72      _proposePosition: function (align, root, node) {
  73        var p = JX.$V(root);
  74        var d = JX.Vector.getDim(root);
  75        var n = JX.Vector.getDim(node);
  76        var l = 0;
  77        var t = 0;
  78  
  79        // Caculate the tip so it's nicely aligned.
  80        switch (align) {
  81          case 'N':
  82            l = parseInt(p.x - ((n.x - d.x) / 2), 10);
  83            t  = parseInt(p.y - n.y, 10);
  84            break;
  85          case 'E':
  86            l = parseInt(p.x + d.x, 10);
  87            t  = parseInt(p.y - ((n.y - d.y) / 2), 10);
  88            break;
  89          case 'S':
  90            l = parseInt(p.x - ((n.x - d.x) / 2), 10);
  91            t  = parseInt(p.y + d.y + 5, 10);
  92            break;
  93          case 'W':
  94            l = parseInt(p.x - n.x - 5, 10);
  95            t  = parseInt(p.y - ((n.y - d.y) / 2), 10);
  96            break;
  97        }
  98  
  99        return new JX.Vector(l, t);
 100      },
 101  
 102      isOnScreen: function (a, node) {
 103        var s = JX.Vector.getScroll();
 104        var v = JX.Vector.getViewport();
 105        var max_x = s.x + v.x;
 106        var max_y = s.y + v.y;
 107  
 108        var corners = this._getNodeCornerPositions(a, node);
 109  
 110        // Check if any of the corners are offscreen
 111        for (var i = 0; i < corners.length; i++) {
 112          var corner = corners[i];
 113          if (corner.x < s.x ||
 114              corner.y < s.y ||
 115              corner.x > max_x ||
 116              corner.y > max_y) {
 117            return false;
 118          }
 119        }
 120        return true;
 121      },
 122  
 123      _getImprovedOrientation: function (a, node) {
 124        // Try to predict the "more correct" orientation
 125        var s = JX.Vector.getScroll();
 126        var v = JX.Vector.getViewport();
 127        var max_x = s.x + v.x;
 128        var max_y = s.y + v.y;
 129  
 130        var corners = this._getNodeCornerPositions(a, node);
 131  
 132        for (var i = 0; i < corners.length; i++) {
 133          var corner = corners[i];
 134          if (corner.y < v.y) {
 135            return 'S';
 136          } else
 137          if (corner.x < v.x) {
 138            return 'E';
 139          } else
 140          if (corner.y > max_y) {
 141            return 'N';
 142          } else
 143          if (corner.x > max_x) {
 144            return 'W';
 145          } else {
 146            return 'N';
 147          }
 148        }
 149      },
 150  
 151      _getNodeCornerPositions: function(pos, node) {
 152        // Get positions of all four corners of a node
 153        var n = JX.Vector.getDim(node);
 154        return [new JX.Vector(pos.x, pos.y),
 155                new JX.Vector(pos.x + n.x, pos.y),
 156                new JX.Vector(pos.x, pos.y + n.y),
 157                new JX.Vector(pos.x + n.x, pos.y + n.y)];
 158      },
 159  
 160      _setAnchor: function (align) {
 161        // Orient the little tail
 162        JX.DOM.alterClass(this._node, 'jx-tooltip-align-' + align, true);
 163      },
 164  
 165      hide : function() {
 166        if (this._node) {
 167          JX.DOM.remove(this._node);
 168          this._node = null;
 169        }
 170      }
 171    }
 172  });


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1