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 })();