1// @ts-check 2 3/** 4 * @constructor 5 * @template {{text: string, icon?: string, selected?: boolean}} T 6 * @param {"platform"|"browser"|"version"} kind 7 * @param {T[]} data 8 * @param {(e: T, i: number)=>void} onSelect 9 */ 10function Dropdown(kind, data, onSelect) { 11 var self = this; 12 13 /** @param {string} cl */ 14 function mkDiv(cl) { 15 var e = document.createElement("div"); 16 e.className = cl; 17 return e; 18 } 19 /** @param {Element} e 20 * @param {string} k */ 21 function toggleAttr(e, k) { 22 var x = e.hasAttribute(k); 23 if (x) { e.removeAttribute(k); } 24 else { e.setAttribute(k, "true"); } 25 return !x; 26 } 27 28 var dd = mkDiv("dropdown kind-" + kind); 29 30 /** @type {(open: boolean) => void} */ 31 self.onToggle = function(){}; 32 33 var ddSel = mkDiv("dropdown-selected"); 34 ddSel.addEventListener("click", function() { 35 var open = toggleAttr(dd, "data-open"); 36 self.onToggle(open); 37 }); 38 dd.appendChild(ddSel); 39 40 var ddItems = mkDiv("dropdown-slider"); 41 ddItems.addEventListener("click", function(e) { 42 if (!e.target) { return; } 43 var dataI = /** @type {Element} */(e.target).getAttribute("data-i"); 44 if (!dataI) { return; } 45 var i = parseInt(dataI); 46 setSel(i); 47 onSelect(self.selectedItem, self.selectedIndex); 48 dd.removeAttribute("data-open"); 49 self.onToggle(false); 50 }); 51 dd.appendChild(ddItems); 52 53 /** @type {T[]} */ 54 self.data = data; 55 /** @type {number} */ 56 self.selectedIndex = -1; 57 /** @type {T} */ 58 self.selectedItem = data[0]; 59 60 /** @type {(i: number) => void} */ 61 function setSel(i) { 62 self.selectedIndex = i; 63 self.selectedItem = self.data[i]; 64 ddSel.innerHTML = ""; 65 ddSel.appendChild(ddItems.children[i].cloneNode(true)); 66 } 67 68 /** @type {(x: T, i: number) => void} */ 69 function addItem(x, i) { 70 var item = mkDiv("item"); 71 item.setAttribute("data-i", i+""); 72 if (x.icon) { 73 var icon = mkDiv("icon"); 74 var img = document.createElement("img"); 75 img.src = x.icon; 76 icon.appendChild(img); 77 item.appendChild(icon); 78 } 79 var text = mkDiv("text"); 80 text.textContent = x.text; 81 item.appendChild(text); 82 ddItems.appendChild(item); 83 if (x.selected) { 84 setSel(i); 85 } 86 } 87 88 /** @type {(data: T[]) => void} */ 89 self.update = function(data) { 90 self.data = data; 91 ddItems.innerHTML = ""; 92 ddSel.innerHTML = ""; 93 self.selectedIndex = -1; 94 95 for (var i = 0; i < self.data.length; i++) { 96 addItem(self.data[i], i); 97 } 98 99 if (self.selectedIndex == -1) { 100 setSel(0); 101 } 102 } 103 self.update(data); 104 105 self.create = function() { return dd }; 106}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.