github.com/elves/elvish@v0.15.0/website/home.js (about) 1 document.addEventListener('DOMContentLoaded', function() { 2 var current = 0, 3 expanded = true; 4 demoWindow = document.getElementById("demo-window"), 5 demoContainer = document.getElementById("demo-container"), 6 demoSwitcher = document.getElementById("demo-switcher"), 7 demoWrappers = document.getElementsByClassName("demo-wrapper"), 8 nDemos = demoWrappers.length, 9 switcherLinks = []; 10 11 /* Functions for scrolling to a certain demo. */ 12 13 function scrollTo(to, instant) { 14 if (expanded) { 15 return; 16 } 17 switcherLinks[current].className = ""; 18 switcherLinks[to].className = "current"; 19 20 var translate = -demoWrappers[0].offsetWidth * to; 21 demoContainer.className = instant ? "" : "animated-transition"; 22 demoContainer.style.transform = "translateX(" + translate + "px)"; 23 24 current = to; 25 }; 26 function scrollToNext() { 27 scrollTo(current < nDemos - 1 ? current + 1 : current); 28 }; 29 function scrollToPrev() { 30 scrollTo(current > 0 ? current - 1 : current); 31 }; 32 33 /* Build the expander. */ 34 35 var li = document.createElement("li"), 36 expander = document.createElement("a"); 37 expander.textContent = "↧"; 38 li.appendChild(expander); 39 demoSwitcher.appendChild(li); 40 41 function expand() { 42 expanded = true; 43 expander.className = "current"; 44 switcherLinks[current].className = ""; 45 demoContainer.className = "expanded"; 46 demoContainer.style.transform = ""; 47 expander.textContent = "↥"; 48 } 49 function collapse() { 50 switcherLinks[current].className = "current"; 51 expander.className = ""; 52 demoContainer.className = ""; 53 expander.textContent = "↧"; 54 } 55 function toggleExpand() { 56 expanded = !expanded; 57 if (expanded) { 58 expand(); 59 } else { 60 collapse(); 61 scrollTo(current, true); 62 } 63 } 64 65 expander.onclick = toggleExpand; 66 67 /* Build demo switchers. */ 68 69 for (var i = 0; i < nDemos; i++) { 70 var li = document.createElement("li"), 71 link = document.createElement("a"); 72 link.textContent = i + 1; 73 link.onclick = (function(to) { return function() { 74 if (expanded) { 75 expanded = false; 76 collapse(); 77 scrollTo(to, true); 78 } else { 79 scrollTo(to); 80 } 81 }; })(i); 82 if (i == 0) { 83 link.className = "current"; 84 } 85 switcherLinks.push(link); 86 li.appendChild(link); 87 demoSwitcher.appendChild(li); 88 } 89 90 /* Switcher built. Hide the warning text, show the expand button, unexpand 91 * and hide scrollbar. */ 92 document.getElementById('no-js').className = "no-display"; 93 demoContainer.className = ""; 94 expanded = false; 95 96 /* Resizing breaks sliding, fix it. */ 97 window.addEventListener('resize', function() { scrollTo(current, true); }); 98 99 /* Scrolling primitives. */ 100 var scrollXTrigger = 5, scrollYTrigger = 5; 101 var scrollX = false, scrollY = false; 102 var offsetX = 0, offsetY = 0, baseOffset = 0; 103 function handleScroll(ev) { 104 if (!scrollX && !scrollY) { 105 if (Math.abs(offsetX) > scrollXTrigger) { 106 baseOffset = offsetX; 107 scrollX = true; 108 } else if (Math.abs(offsetY) > scrollYTrigger) { 109 baseOffset = offsetY; 110 scrollY = true; 111 } 112 } 113 if (!scrollX) { 114 return; 115 } 116 // No overscrolling. 117 var calculatedOffset = offsetX - baseOffset; 118 if ((current == 0 && calculatedOffset > 0) || 119 (current == nDemos-1 && calculatedOffset < 0)) { 120 calculatedOffset = 0; 121 } 122 var translate = calculatedOffset - demoWrappers[0].offsetWidth * current; 123 demoContainer.style.transform = "translateX(" + translate + "px)"; 124 ev.preventDefault(); 125 } 126 function settleScroll() { 127 if (scrollX) { 128 var threshold = Math.min(60, demoWindow.offsetWidth / 4); 129 if (offsetX < -threshold) { 130 scrollToNext(); 131 } else if (offsetX > threshold) { 132 scrollToPrev(); 133 } else { 134 scrollTo(current); 135 } 136 } 137 offsetX = offsetY = baseOffset = 0; 138 scrollX = scrollY = false; 139 } 140 141 /* Support scrolling by touch. */ 142 var initX, initY; 143 demoWindow.addEventListener('touchstart', function(ev) { 144 if (expanded) { 145 return; 146 } 147 initX = ev.touches[0].clientX; 148 initY = ev.touches[0].clientY; 149 demoContainer.className = ""; 150 }); 151 demoWindow.addEventListener('touchmove', function(ev) { 152 if (expanded) { 153 return; 154 } 155 if (ev.touches.length == 1) { 156 var lastX = ev.touches[0].clientX; 157 var lastY = ev.touches[0].clientY; 158 offsetX = lastX - initX; 159 offsetY = lastY - initY; 160 handleScroll(ev); 161 // document.getElementById('demo-debug').innerText = '(' + offsetX + ', ' + offsetY + '), ' + scrollX + ', ' + scrollY; 162 } 163 }); 164 demoWindow.addEventListener('touchcancel', function() { 165 if (expanded) { 166 return; 167 } 168 scrollTo(current); 169 }); 170 demoWindow.addEventListener('touchend', function() { 171 if (expanded) { 172 return; 173 } 174 settleScroll(); 175 }); 176 177 // Keyboard bindings. 178 window.addEventListener('keypress', function(ev) { 179 var char = String.fromCodePoint(ev.keyCode || ev.charCode); 180 if (char == 'h') { 181 scrollToPrev(); 182 } else if (char == 'l') { 183 scrollToNext(); 184 } else if (char == 'o') { 185 toggleExpand(); 186 } else { 187 var i = parseInt(char); 188 if (1 <= i && i <= nDemos) { 189 if (expanded) { 190 expanded = false; 191 collapse(); 192 } 193 scrollTo(i-1); 194 } 195 } 196 }); 197 });