github.com/everlongproject/i18n4go@v0.2.7-0.20201028180611-670cbaceaa6b/slack/slackin.js (about)

     1  (function(){
     2  
     3    // give up and resort to `target=_blank`
     4    // if we're not modern enough
     5    if (!document.body.getBoundingClientRect
     6     || !document.body.querySelectorAll
     7     || !window.postMessage) {
     8      return;
     9    }
    10  
    11    // search for a script tag pointing to slackin.js
    12    function search(){
    13      var replaced = 0;
    14      var scripts = document.querySelectorAll('script');
    15      var script;
    16      for (var i = 0; i < scripts.length; i++) {
    17        script = scripts[i];
    18        if (!script.src) continue;
    19        if (/\/slackin\.js(\?.*)?$/.test(script.src)) {
    20          // replace script with iframe
    21          replace(script);
    22  
    23          // we abort the search for subsequent
    24          // slackin.js executions to exhaust
    25          // the queue
    26          return true;
    27        }
    28      }
    29    }
    30  
    31    // replace the script tag with an iframe
    32    function replace(script){
    33      var parent = script.parentNode;
    34      if (!parent) return;
    35  
    36      var large = /\?large/.test(script.src);
    37      var iframe = document.createElement('iframe');
    38      var iframePath = '/iframe' + (large ? '?large' : '');
    39      iframe.src = script.src.replace(/\/slackin\.js.*/, iframePath);
    40      iframe.style.borderWidth = 0;
    41      iframe.className = '__slackin';
    42  
    43      // a decent aproximation that we adjust later
    44      // once we have the knowledge of the actual
    45      // numbers of users, based on a user count
    46      // of 3 digits by 3 digits
    47      iframe.style.width = (large ? 171 : 114) + 'px';
    48  
    49      // height depends on target size
    50      iframe.style.height = (large ? 30 : 20) + 'px';
    51  
    52      // hidden by default to avoid flicker
    53      iframe.style.visibility = 'hidden';
    54  
    55      parent.insertBefore(iframe, script);
    56      parent.removeChild(script);
    57  
    58      // setup iframe RPC
    59      iframe.onload = function(){
    60        setup(iframe);
    61      };
    62    }
    63  
    64    // setup an "RPC" channel between iframe and us
    65    function setup(iframe){
    66      var id = Math.random() * (1 << 24) | 0;
    67      iframe.contentWindow.postMessage('slackin:' + id, '*');
    68      window.addEventListener('message', function(e){
    69        // show dialog upon click
    70        if ('slackin-click:' + id  == e.data) {
    71          showDialog(iframe);
    72        }
    73  
    74        // update width
    75        var wp = 'slackin-width:' + id + ':';
    76        if (wp == e.data.substr(0, wp.length)) {
    77          var width = e.data.substr(wp.length);
    78          iframe.style.width = width + 'px';
    79  
    80          // ensure it's shown (since first time hidden)
    81          iframe.style.visibility = 'visible';
    82        }
    83      });
    84    }
    85  
    86    // show the dialog around the iframe
    87    // by, yes, creating a new iframe
    88    var showing = false;
    89    function showDialog(iframe){
    90      if (showing) return;
    91      showing = true;
    92  
    93      // container div
    94      var div = document.createElement('div');
    95      div.className = '__slackin';
    96      div.style.border = '1px solid #D6D6D6';
    97      div.style.padding = '0';
    98      div.style.margin = '0';
    99      div.style.lineHeight = '0';
   100      div.style.backgroundColor = '#FAFAFA';
   101      div.style.width = '250px';
   102      div.style.height = '124px';
   103      div.style.position = 'absolute';
   104      div.style.left = '-10000px';
   105      div.style.top = '-10000px';
   106      div.style.borderRadius = '4px';
   107      div.style.padding = '4px';
   108      div.style.boxSizing = 'content-box';
   109  
   110      // new iframe
   111      var ni = document.createElement('iframe');
   112      ni.className = '__slackin';
   113      ni.style.width = '250px';
   114      ni.style.height = '124px';
   115      ni.style.borderWidth = 0;
   116      ni.src = iframe.src.replace(/\?.*/, '') + '/dialog';
   117      ni.onload = function(){
   118        window.addEventListener('scroll', dposition);
   119        window.addEventListener('resize', dposition);
   120        position();
   121      };
   122  
   123      // arrows
   124      var a1 = document.createElement('div');
   125      var a2 = document.createElement('div');
   126      [a1, a2].forEach(function(a){
   127        a.style.border = 'solid transparent';
   128        a.style.pointerEvents = 'none';
   129        a.style.width = '0';
   130        a.style.height = '0';
   131        a.style.margin = '0';
   132        a.style.padding = '0';
   133        a.style.position = 'absolute';
   134        a.style.display = 'inline';
   135      });
   136  
   137      a1.style.borderColor = 'rgba(214, 214, 214, 0)';
   138      a2.style.borderColor = 'rgba(250, 250, 250, 0)';
   139  
   140      a1.style.borderWidth = '7px';
   141      a1.style.marginLeft = '-7px';
   142      a2.style.borderWidth = '6px';
   143      a2.style.marginLeft = '-6px';
   144  
   145      // append
   146      div.appendChild(a1);
   147      div.appendChild(a2);
   148      div.appendChild(ni);
   149      document.body.appendChild(div);
   150  
   151      function position(){
   152        [div, a1, a2].forEach(function(el){
   153          el.style.left = '';
   154          el.style.right = '';
   155          el.style.bottom = '';
   156          el.style.top = '';
   157        });
   158  
   159        var divPos = div.getBoundingClientRect();
   160        var iframePos = iframe.getBoundingClientRect();
   161        var divHeight = divPos.height + 9; // arrow height
   162  
   163        var st = document.body.scrollTop;
   164        var sl = document.body.scrollLeft;
   165        var iw = window.innerWidth;
   166        var ih = window.innerHeight;
   167        var iframeTop = iframePos.top + st;
   168        var iframeLeft = iframePos.left + sl;
   169  
   170        // position vertically / arrows
   171        if (st + iframePos.bottom + divHeight > st + ih) {
   172          div.style.top = (iframeTop - divHeight) + 'px';
   173          a1.style.top = a2.style.top = '100%';
   174  
   175          a1.style.borderBottomColor = 'rgba(214, 214, 214, 0)';
   176          a2.style.borderBottomColor = 'rgba(250, 250, 250, 0)';
   177          a1.style.borderTopColor = '#d6d6d6';
   178          a2.style.borderTopColor = '#fafafa';
   179        } else {
   180          div.style.top = (iframeTop + iframePos.height + 9) + 'px';
   181          a1.style.bottom = a2.style.bottom = '100%';
   182  
   183          a1.style.borderTopColor = 'rgba(214, 214, 214, 0)';
   184          a2.style.borderTopColor = 'rgba(250, 250, 250, 0)';
   185          a1.style.borderBottomColor = '#d6d6d6';
   186          a2.style.borderBottomColor = '#fafafa';
   187        }
   188  
   189        // position horizontally
   190        var left = iframePos.left
   191          + Math.round(iframePos.width / 2)
   192          - Math.round(divPos.width / 2);
   193        if (left < sl) left = sl;
   194        if (left + divPos.width > sl + iw) {
   195          left = sl + iw - divPos.width;
   196        }
   197        div.style.left = left + 'px';
   198  
   199        a1.style.left =
   200        a2.style.left = (iframeLeft - left + Math.round(iframePos.width / 2)) + 'px';
   201      }
   202  
   203      // debounced positionining
   204      var timer;
   205      function dposition(){
   206        clearTimeout(timer);
   207        timer = setTimeout(position, 100);
   208      }
   209  
   210      function hide(){
   211        showing = false;
   212        window.removeEventListener('scroll', dposition);
   213        window.removeEventListener('resize', dposition);
   214        document.body.removeChild(div);
   215        document.documentElement.removeEventListener('click', click, true);
   216      }
   217  
   218      function click(ev){
   219        if ('__slackin' != ev.target.className) {
   220          hide();
   221        }
   222      }
   223  
   224      document.documentElement.addEventListener('click', click, true);
   225    }
   226  
   227    var found = search();
   228    if (!found) setTimeout(search, 5000);
   229  
   230  })();