1(function () { 2 'use strict'; 3 4 // Only run on devices that support hover 5 var supportsHover = window.matchMedia && window.matchMedia('(hover: hover)').matches; 6 7 // Find the Products link in the primary header nav 8 function findProductsLink() { 9 // Scope to primary header nav to avoid picking footer duplicates 10 var candidate = document.querySelector('#divPrimaryNavBar nav ul li a[href="/products"]'); 11 if (candidate) return candidate; 12 // Fallback if structure changes slightly 13 return document.querySelector('header a[href="/products"]'); 14 } 15 16 var productsLink = findProductsLink(); 17 if (!productsLink) return; // nothing to do 18 19 // Data model: 3 columns, each with { name, href, icon, desc } 20 // Data model: columns, each with { name, href, icon, desc } 21 var menuData = { 22 "File & Upload Security": [ 23 { name: "Virus Scan APIs", href: "/virus-api", icon: "/images/shield.svg", desc: "Scan files and content for viruses and identify security issues with content." }, 24 { name: "Content Disarm & Reconstruction (CDR) API", href: "/content-disarm-and-reconstruction-cdr-api", icon: "/images/crosshair.svg", desc: "Remove embedded security threats from user documents via CDR." }, 25 { name: "Spam Detection API", href: "/spam-detection-api", icon: "/images/alert-triangle.svg", desc: "Scan input text and email for spam and other security threats using Advanced AI." }, 26 { name: "Fraud Detection API", href: "/ai-fraud-detection-api", icon: "/images/flag.svg", desc: "Scan documents for fraud indicators and other security threats using Advanced AI." }, 27 { name: "Content Moderation API", href: "/content-moderation-api", icon: "/images/file-minus.svg", desc: "Moderate content, including images, website URLs and files for raciness, not-safe-for-work content, viruses, malware, and other issues with advanced APIs." }, 28 { name: "Security Threat Detection APIs", href: "/security-threat-detection-api", icon: "/images/activity.svg", desc: "Detect and block security threats via API." }, 29 { name: "Data Loss Prevention (DLP) API", href: "/data-loss-prevention-dlp-api", icon: "/images/scan-search.svg", desc: "Detect, redact, and protect PII, PHI, and financial data in text and documents." } 30 ], 31 32 "Application Security": [ 33 { name: "Virus Scanning Reverse Proxy Server", href: "/virus-scanning-reverse-proxy", icon: "/images/server.svg", desc: "Protect your web application or web APIs automatically from virus uploads using a reverse proxy." }, 34 { name: "AI Web Application Firewall", href: "/ai-waf", icon: "/images/lock.svg", desc: "Automatically protect your application from attacks with stateâofâtheâart AI security." }, 35 { name: "ICAP AntiâVirus Scanning Server", href: "/icap-anti-virus-scan-server", icon: "/images/share-2.svg", desc: "Scan files over the ICAP protocol to identify viruses and other threats." } 36 ], 37 38 "AI Security": [ 39 { name: "MCP Server", href: "/mcp-server", icon: "/images/server-cog.svg", desc: "Securely connect AI agents and LLMs to your tools and data with the Enterprise MCP Server." } 40 ], 41 42 "Endpoint Security": [ 43 { name: "Virus Scanning Forward Proxy Server", href: "/virus-scanning-forward-proxy", icon: "/images/share-2.svg", desc: "Protect endpoints from malicious outbound traffic, malware, and viruses via a forward proxy." } 44 ], 45 46 "Storage Security": [ 47 { name: "AWS S3 AntiâVirus Scanning", href: "/aws-s3-anti-virus-scanning", icon: "/images/cloud-lightning.svg", desc: "Automatically protect AWS S3 buckets from viruses and malware â no code changes, real time." }, 48 { name: "Azure Blob AntiâVirus Scanning", href: "/azure-blob-storage-anti-virus-scanning", icon: "/images/hard-drive.svg", desc: "Automatically protect Azure Blob Storage from viruses and malware â no code changes, real time." }, 49 { name: "SMB File Share AntiâVirus", href: "/smb-file-share-anti-virus-scanning", icon: "/images/file-plus.svg", desc: "Protect files and folders in SMB/CIFS shares from viruses and malware â no code changes." }, 50 { name: "GCP Storage AntiâVirus Scanning", href: "/google-cloud-gcp-anti-virus-scanning", icon: "/images/cloud-drizzle.svg", desc: "Protect Google Cloud Storage objects from viruses and malware â no code changes, real time." }, 51 ], 52 53 "SaaS Security": [ 54 { name: "SharePoint AntiâVirus Scanning", href: "/sharepoint-anti-virus-scanning", icon: "/images/cloud-snow.svg", desc: "Automatically protect SharePoint Document Libraries and Sites from viruses and malware." }, 55 { name: "Freshdesk AntiâVirus Scanning", href: "/freshdesk-virus-scan-protection", icon: "/images/cloud-lightning.svg", desc: "Automatically protect any Freshdesk channel from viruses and malware in real time." } 56 ], 57 58 "Email Security": [ 59 { name: "Email Virus Scanning", href: "/email-virus-scanning", icon: "/images/mail.svg", desc: "Scan emails and attachments for viruses and threats in real time." }, 60 { name: "Phishing Detection API", href: "/phishing-detection-api", icon: "/images/at-sign.svg", desc: "Scan emails, text, and documents for phishing using Advanced AI." } 61 ], 62 63 64 65 "Business Automation": [ 66 { name: "Document Processing APIs", href: "/convert-api", icon: "/images/file.svg", desc: "Convert files and data effortlessly. Convert DOCX to PDF. Convert CSV to JSON. Screenshot URLs to PNG or PDF. Convert images between over 100 file formats. And much more." }, 67 { name: "Document AI APIs", href: "/document-ai-api", icon: "/images/robot.svg", desc: "Extract fields, data, insights, and text from documents instantly using AI." }, 68 { name: "Data Validation APIs", href: "/validate-api", icon: "/images/check.svg", desc: "Validate emails, domains, and IP addresses (including geolocation) and more." }, 69 { name: "Currency APIs", href: "/currency-api", icon: "/images/currency.svg", desc: "Convert prices with realâtime rates across 30+ currencies." }, 70 { name: "Barcode APIs", href: "/barcode-api", icon: "/images/zap.svg", desc: "Generate and recognize 1D and 2D barcodes." }, 71 { name: "Video & Media Services APIs", href: "/video-and-media-services-api", icon: "/images/video.svg", desc: "Convert and encode video/media between formats on demand." }, 72 { name: "Data Integration APIs", href: "/data-integration-api", icon: "/images/database.svg", desc: "Query database backup files directly and convert them into other formats." } 73 ], 74 75 "Artificial Intelligence": [ 76 { name: "OCR APIs", href: "/ocr-api", icon: "/images/aperture.svg", desc: "Convert scans/photos of documents to rich text; auto deâskew & deârotate." }, 77 { name: "Image & Face Recognition APIs", href: "/image-recognition-and-processing-api", icon: "/images/eye.svg", desc: "Captioning, face recognition, NSFW classification, and powerful image ops." }, 78 { name: "Natural Language Processing (NLP) APIs", href: "/nlp-api", icon: "/images/message-circle.svg", desc: "POS tagging, entity extraction, parsing, and more for unstructured text." }, 79 { name: "Voice Recognition & Speech APIs", href: "/voice-recognition-and-speech-api", icon: "/images/mic.svg", desc: "Speechâtoâtext and textâtoâspeech using advanced ML. (Preview)" } 80 ] 81 }; 82 83 84 // Build DOM 85 var menuEl = document.createElement('div'); 86 menuEl.id = 'cmProductsMega'; 87 menuEl.className = 'cm-megamenu'; 88 menuEl.setAttribute('role', 'region'); 89 menuEl.setAttribute('aria-label', 'Products submenu'); 90 menuEl.setAttribute('aria-hidden', 'true'); 91 92 var grid = document.createElement('div'); 93 grid.className = 'cm-megamenu__grid'; 94
95 Object.keys(menuData).forEach(function (colName) { 96 var col = document.createElement('div'); 97 col.className = 'cm-megamenu__col'; 98 99 var h = document.createElement('div'); 100 h.className = 'cm-megamenu__heading'; 101 h.textContent = colName; 102 col.appendChild(h); 103 104 var ul = document.createElement('ul'); 105 ul.className = 'cm-megamenu__list'; 106 107 menuData[colName].forEach(function (item) { 108 var li = document.createElement('li'); 109 li.className = 'cm-megamenu__item'; 110 111 var a = document.createElement('a'); 112 a.className = 'cm-megamenu__link'; 113 a.href = item.href; 114 a.setAttribute('tabindex', '0'); 115 116 var img = document.createElement('img'); 117 img.className = 'cm-megamenu__icon'; 118 img.src = item.icon; 119 img.alt = ''; // decorative 120 121 var span = document.createElement('span'); 122 span.className = 'cm-megamenu__label'; 123 span.textContent = item.name; 124 125 var tip = document.createElement('div'); 126 tip.className = 'cm-tooltip'; 127 tip.innerHTML = escapeHTML(item.desc); 128 129 a.appendChild(img); 130 a.appendChild(span); 131 a.appendChild(tip); 132 li.appendChild(a); 133 ul.appendChild(li); 134 }); 135 136 col.appendChild(ul); 137 grid.appendChild(col); 138 }); 139 140 // Optional footer: View all products 141 var footer = document.createElement('div'); 142 footer.className = 'cm-megamenu__footer'; 143 var all = document.createElement('a'); 144 all.href = '/products'; 145 all.textContent = 'View all products â'; 146 footer.appendChild(all); 147 148 menuEl.appendChild(grid); 149 menuEl.appendChild(footer); 150 document.body.appendChild(menuEl); 151 152 // Accessibility on trigger 153 productsLink.setAttribute('aria-haspopup', 'true'); 154 productsLink.setAttribute('aria-expanded', 'false'); 155 productsLink.setAttribute('aria-controls', menuEl.id); 156 157 // Hover/focus behavior 158 var hideTimer = 0; 159 160 function openMenu() { 161 if (!supportsHover) return; 162 clearTimeout(hideTimer); 163 menuEl.classList.add('cm-show'); 164 menuEl.setAttribute('aria-hidden', 'false'); 165 productsLink.setAttribute('aria-expanded', 'true'); 166 positionMenu(); 167 } 168 169 function scheduleClose() { 170 clearTimeout(hideTimer); 171 hideTimer = window.setTimeout(closeMenu, 140); 172 } 173 174 function closeMenu() { 175 menuEl.classList.remove('cm-show'); 176 menuEl.setAttribute('aria-hidden', 'true'); 177 productsLink.setAttribute('aria-expanded', 'false'); 178 } 179 180 // Reposition under the Products link 181 function positionMenu() { 182 var rect = productsLink.getBoundingClientRect(); 183 var vw = document.documentElement.clientWidth || window.innerWidth; 184 var scrollX = window.pageXOffset || document.documentElement.scrollLeft || 0; 185 var scrollY = window.pageYOffset || document.documentElement.scrollTop || 0; 186 187 // Ensure itâs visible to measure width 188 var wasHidden = menuEl.style.display === 'none' || window.getComputedStyle(menuEl).display === 'none'; 189 if (wasHidden) { 190 menuEl.style.visibility = 'hidden'; 191 menuEl.style.display = 'block'; 192 } 193 194 var menuW = menuEl.offsetWidth; 195 var idealLeft = rect.left + scrollX - (menuW / 2 - rect.width / 2); 196 var minLeft = scrollX + 12; 197 var maxLeft = scrollX + vw - menuW - 12; 198 var left = Math.max(minLeft, Math.min(idealLeft, maxLeft)); 199 var top = rect.bottom + scrollY + 10; 200 201 menuEl.style.left = left + 'px'; 202 menuEl.style.top = top + 'px'; 203 204 if (wasHidden) { 205 menuEl.style.display = ''; 206 menuEl.style.visibility = ''; 207 } 208 } 209 210 // Event wiring (hover + keyboard + escape + outside click) 211 productsLink.addEventListener('mouseenter', openMenu); 212 productsLink.addEventListener('focus', openMenu); 213 productsLink.addEventListener('mouseleave', scheduleClose); 214 215 menuEl.addEventListener('mouseenter', function () { clearTimeout(hideTimer); }); 216 menuEl.addEventListener('mouseleave', scheduleClose); 217 218 window.addEventListener('scroll', function () { 219 if (menuEl.classList.contains('cm-show')) positionMenu(); 220 }, { passive: true });
221 222 window.addEventListener('resize', function () { 223 if (menuEl.classList.contains('cm-show')) positionMenu(); 224 }); 225 226 document.addEventListener('keydown', function (e) { 227 if (e.key === 'Escape') closeMenu(); 228 }); 229 230 document.addEventListener('click', function (e) { 231 if (!menuEl.classList.contains('cm-show')) return; 232 if (menuEl.contains(e.target) || productsLink.contains(e.target)) return; 233 closeMenu(); 234 }); 235 236 // Util: best-effort HTML escape for tooltip content 237 function escapeHTML(str) { 238 return String(str) 239 .replace(/&/g, '&') 240 .replace(/</g, '<') 241 .replace(/>/g, '>'); 242 } 243})();
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.