From 14f1d4f4fbd32b15e85e138fb4f5462af058bd60 Mon Sep 17 00:00:00 2001 From: Kelvin-Macapagal Date: Tue, 16 Jun 2026 08:45:30 +0800 Subject: [PATCH 01/13] Add logic for Vietnam region for cookie compliance and add footer --- src/apisof.net/Pages/_Host.cshtml | 44 +++++++++++++++ src/apisof.net/Shared/MainLayout.razor | 44 ++++++++++++++- src/apisof.net/wwwroot/css/site.css | 77 ++++++++++++++++++++++++++ 3 files changed, 164 insertions(+), 1 deletion(-) diff --git a/src/apisof.net/Pages/_Host.cshtml b/src/apisof.net/Pages/_Host.cshtml index 14f066af..9a94d0ad 100644 --- a/src/apisof.net/Pages/_Host.cshtml +++ b/src/apisof.net/Pages/_Host.cshtml @@ -16,8 +16,11 @@ + + + @@ -37,6 +40,47 @@ - + diff --git a/src/apisof.net/wwwroot/js/site.js b/src/apisof.net/wwwroot/js/site.js new file mode 100644 index 00000000..00f728ec --- /dev/null +++ b/src/apisof.net/wwwroot/js/site.js @@ -0,0 +1,79 @@ +var siteConsent = null; + +function setCookieManagementVisibility(isVisible) { + var elements = document.querySelectorAll(".manageCookieChoice"); + for (var i = 0; i < elements.length; i++) { + elements[i].style.display = isVisible ? "list-item" : "none"; + } +} + +function initializeCookieConsent() { + if (typeof WcpConsent === "undefined" || typeof WcpConsent.init !== "function") { + return; + } + + WcpConsent.init("en-US", "cookie-banner", function (err, consentInstance) { + if (err || !consentInstance) { + return; + } + + siteConsent = consentInstance; + setCookieManagementVisibility(!!siteConsent.isConsentRequired); + + if (typeof siteConsent.onConsentChanged === "function") { + siteConsent.onConsentChanged(function () { + setCookieManagementVisibility(!!siteConsent.isConsentRequired); + }); + } + }); +} + +function manageConsent() { + if (siteConsent && typeof siteConsent.manageConsent === "function") { + siteConsent.manageConsent(); + } +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", initializeCookieConsent); +} else { + initializeCookieConsent(); +} + +function scrollIntoMainContent() { + var mainContent = document.getElementById("main-content"); + if (mainContent) { + mainContent.scrollIntoView({ behavior: "smooth" }); + mainContent.focus(); + } +} + +var observer = new MutationObserver(function () { + $('[data-toggle="popover"]').popover({ + placement: 'top', + trigger: 'hover', + boundary: 'body' + }); + $('[data-toggle="popover"]').on('click', function () { + $('[data-toggle="popover"]').popover('dispose'); + }); + $('.search-result-row.selected').each(function () { + this.scrollIntoView({ block: "nearest" }); + }); + $("#skipToMain").on('keydown', function (e) { + if (e.key === "Enter" || e.key === " ") { + scrollIntoMainContent(); + e.preventDefault(); + } + }); + $("#skipToMain").on('click', function (e) { + scrollIntoMainContent(); + e.preventDefault(); + }); +}); + +observer.observe(document, { + subtree: true, + childList: true, + attributes: true +}); From f3e3ff0baf763dc8a3fbb5a73381c1402452ccc3 Mon Sep 17 00:00:00 2001 From: Kelvin-Macapagal Date: Mon, 22 Jun 2026 22:47:00 +0800 Subject: [PATCH 03/13] pr review update --- src/apisof.net/wwwroot/css/site.css | 264 ++++++++++++++-------------- 1 file changed, 128 insertions(+), 136 deletions(-) diff --git a/src/apisof.net/wwwroot/css/site.css b/src/apisof.net/wwwroot/css/site.css index f1b1ae23..2cb1c30c 100644 --- a/src/apisof.net/wwwroot/css/site.css +++ b/src/apisof.net/wwwroot/css/site.css @@ -1,7 +1,6 @@ @import url('open-iconic/font/css/open-iconic-bootstrap.min.css'); -:root -{ +:root { --dotnet-purple: #512bd4; --dotnet-purple-hover: #4411BB; --dotnet-purple-border-hover: #3311BB; @@ -19,11 +18,11 @@ border-color: var(--dotnet-purple); } - .btn-dotnet:hover { - color: #fff; - background-color: var(--dotnet-purple-hover); - border-color: var(--dotnet-purple-border-hover); - } +.btn-dotnet:hover { + color: #fff; + background-color: var(--dotnet-purple-hover); + border-color: var(--dotnet-purple-border-hover); +} #blazor-error-ui { background: lightyellow; @@ -37,12 +36,12 @@ z-index: 1000; } - #blazor-error-ui .dismiss { - cursor: pointer; - position: absolute; - right: 0.75rem; - top: 0.5rem; - } +#blazor-error-ui .dismiss { + cursor: pointer; + position: absolute; + right: 0.75rem; + top: 0.5rem; +} .breadcrumb { border-radius: 0rem; @@ -67,35 +66,33 @@ code { color: unset !important; } -a, a:link, a:visited -{ +a, +a:link, +a:visited { color: var(--dotnet-catalog-link-color); } .btn-primary { background-color: #0071EB !important; - color:#fff !important; + color: #fff !important; } .btn-info { background-color: #117C8D; } -.btn-secondary -{ +.btn-secondary { color: #f8ffff !important; } /* Stats */ -.statistics-table.table td:nth-child(2) -{ +.statistics-table.table td:nth-child(2) { text-align: right; } /* Search */ -.modal -{ +.modal { display: none; } @@ -111,38 +108,33 @@ a, a:link, a:visited margin-right: 5%; } -.modal-dialog -{ +.modal-dialog { height: 100%; max-height: 90vh; } -.modal-content -{ +.modal-content { max-height: 100%; display: flex; flex-direction: column; } -.modal-body -{ +.modal-body { display: flex; flex-direction: column; min-height: 0; } -.modal-body .search-input{ - max-height:30px; +.modal-body .search-input { + max-height: 30px; } -.search-results -{ +.search-results { overflow-y: auto; max-height: 90%; } -.search-result-row -{ +.search-result-row { color: var(--color-text-primary); border-radius: 0.25rem; padding: 0.25rem; @@ -152,10 +144,10 @@ a, a:link, a:visited cursor: pointer; } - .search-result-row.selected { - color: white; - background-color: #006ee5; - } +.search-result-row.selected { + color: white; + background-color: #006ee5; +} /* Diff */ @@ -225,11 +217,13 @@ a, a:link, a:visited right: 0; } -.syntax-view.diff-added, .syntax-view .diff-added { +.syntax-view.diff-added, +.syntax-view .diff-added { background: rgba(46, 139, 87, 0.2); } -.syntax-view.diff-removed, .syntax-view .diff-removed { +.syntax-view.diff-removed, +.syntax-view .diff-removed { background: rgba(178, 34, 34, 0.2); } @@ -303,66 +297,68 @@ a, a:link, a:visited background-color: rgb(40, 40, 40); } - .syntax-view.diff-added, .syntax-view .diff-added { + .syntax-view.diff-added, + .syntax-view .diff-added { background: rgba(46, 139, 87, 0.3); } - .syntax-view.diff-removed, .syntax-view .diff-removed { + .syntax-view.diff-removed, + .syntax-view .diff-removed { background: rgba(178, 34, 34, 0.3); } - .syntax-view pre { - color: rgb(220, 220, 220); - } + .syntax-view pre { + color: rgb(220, 220, 220); + } - .syntax-view .keyword { - color: rgb(86, 156, 214); - } + .syntax-view .keyword { + color: rgb(86, 156, 214); + } - .syntax-view .annotation { - background-color: rgb(75, 75, 75); - color: rgb(220, 220, 220); - } + .syntax-view .annotation { + background-color: rgb(75, 75, 75); + color: rgb(220, 220, 220); + } - .syntax-view .punctuation { - color: rgb(220, 220, 220); - } + .syntax-view .punctuation { + color: rgb(220, 220, 220); + } - .syntax-view .string { - color: rgb(214, 157, 133); - } + .syntax-view .string { + color: rgb(214, 157, 133); + } - .syntax-view .number { - color: rgb(181, 206, 168); - } + .syntax-view .number { + color: rgb(181, 206, 168); + } - .syntax-view .class a { - color: rgb(78, 201, 176); - } + .syntax-view .class a { + color: rgb(78, 201, 176); + } - .syntax-view .delegate a { - color: rgb(78, 201, 176); - } + .syntax-view .delegate a { + color: rgb(78, 201, 176); + } - .syntax-view .enum a { - color: rgb(184, 215, 163); - } + .syntax-view .enum a { + color: rgb(184, 215, 163); + } - .syntax-view .struct a { - color: rgb(134, 198, 145); - } + .syntax-view .struct a { + color: rgb(134, 198, 145); + } - .syntax-view .interface a { - color: rgb(184, 215, 163); - } + .syntax-view .interface a { + color: rgb(184, 215, 163); + } - .syntax-view .reference a { - color: rgb(220, 220, 220); - } + .syntax-view .reference a { + color: rgb(220, 220, 220); + } - .syntax-view .reference { - color: rgb(220, 220, 220); - } + .syntax-view .reference { + color: rgb(220, 220, 220); + } } /* Section Row */ @@ -375,42 +371,44 @@ a, a:link, a:visited .section-row { background-color: rgb(52, 58, 64); } - a, a:link, a:visited - { + + a, + a:link, + a:visited { color: var(--dotnet-catalog-link-dark-color); } - .btn-outline-secondary - { + + .btn-outline-secondary { color: #F7F7F7; border-color: #676E76; background-color: #676E76; } - .btn-outline-secondary:hover - { + + .btn-outline-secondary:hover { color: #fff; border-color: #525960; background-color: #525960; } - .breadcrumb .breadcrumb-item.active - { + + .breadcrumb .breadcrumb-item.active { color: #97a5b1; } - .text-muted - { + + .text-muted { color: #7b868f !important; } - .btn-primary - { + + .btn-primary { background-color: #0071EB !important; color: #f8ffff !important; } - .btn-info - { + + .btn-info { background-color: #117C8D; color: #f8ffff; } - .btn-secondary - { + + .btn-secondary { color: #f8ffff !important; } } @@ -448,18 +446,20 @@ a, a:link, a:visited color: white; } - .fx-version.fx-version-inbox a:link, .fx-version.fx-version-inbox a:visited { - color: white; - } +.fx-version.fx-version-inbox a:link, +.fx-version.fx-version-inbox a:visited { + color: white; +} .fx-version.fx-version-package { background-color: hsl(253, 56%, 80%); color: black; } - .fx-version.fx-version-package a:link, .fx-version.fx-version-package a:visited { - color: black; - } +.fx-version.fx-version-package a:link, +.fx-version.fx-version-package a:visited { + color: black; +} .fx-version.fx-selected { font-weight: bolder; @@ -510,7 +510,8 @@ a, a:link, a:visited overflow: hidden; z-index: -2; - &:focus, &:active { + &:focus, + &:active { background: #e6e6e6; color: #0067b8; position: fixed; @@ -527,14 +528,12 @@ a, a:link, a:visited outline: none; } - &:focus - { + &:focus { border: 1px dashed #000; } } -.flex-inline-breakable -{ +.flex-inline-breakable { display: flex; align-items: center; gap: 0.3rem; @@ -543,8 +542,7 @@ a, a:link, a:visited overflow-wrap: anywhere; } -.text-breakable -{ +.text-breakable { white-space: normal; word-break: break-all; overflow-wrap: anywhere; @@ -566,28 +564,24 @@ a, a:link, a:visited input:not([type="checkbox"]):not([type="radio"]), select, -textarea -{ +textarea { border-color: #1D72CC !important; } input:not([type="checkbox"]):not([type="radio"]):focus, select:focus, -textarea:focus -{ +textarea:focus { border-color: #1D72CC !important; box-shadow: 0 0 0 0.2rem rgba(29, 114, 204, 0.25) !important; outline: none !important; } -.btn:focus -{ +.btn:focus { border-color: #09102A !important; outline: none !important; } -.text-underline -{ +.text-underline { text-decoration: underline; text-decoration-skip-ink: none; text-underline-offset: 2px; @@ -627,7 +621,8 @@ textarea:focus } /* Prevent horizontal overflow on all screens */ -html, body { +html, +body { overflow-x: hidden; width: 100%; } @@ -636,7 +631,7 @@ html, body { gap: 0.4rem; } -.table-responsive-stack th{ +.table-responsive-stack th { min-width: 200px; } @@ -677,7 +672,7 @@ html, body { white-space: nowrap; } -.uhf-footer-links li + li::before { +.uhf-footer-links li+li::before { content: "|"; color: rgba(255, 255, 255, 0.55); margin: 0 0.55rem; @@ -706,41 +701,38 @@ html, body { flex-shrink: 0; } +/* Small screens (mobile and narrow windows) */ @media (max-width: 480px) { .uhf-footer-links { row-gap: 0.25rem; } - .uhf-footer-links li + li::before { + .uhf-footer-links li+li::before { margin: 0 0.4rem; } -} -/* Small screens (mobile and narrow windows) */ -@media (max-width: 480px) -{ /* Container adjustments */ .container-fluid { padding-left: 12px; padding-right: 12px; } - + .table-responsive { margin-left: 0; margin-right: 0; overflow-x: visible; } - + /* Usage section - description goes to next line */ .usage-description { flex-basis: 100%; } - + .usage-progress-bar { min-width: 100px; max-width: 150px; } - + /* Stack table rows */ .table-responsive-stack tr { display: block; @@ -748,20 +740,20 @@ html, body { margin-bottom: 0.5rem; border-radius: 0.25rem; } - + .table-responsive-stack tr.section-row { display: table-row; border: none; margin-bottom: 0; } - + .table-responsive-stack tr.no-border-top { border-top: none; margin-top: -0.5rem; border-top-left-radius: 0; border-top-right-radius: 0; } - + .table-responsive-stack th, .table-responsive-stack td { display: block; @@ -771,13 +763,13 @@ html, body { width: 100% !important; box-sizing: border-box; } - + .table-responsive-stack td { padding-top: 0.25rem; border-bottom-left-radius: 0.25rem; border-bottom-right-radius: 0.25rem; } - + /* Ensure version badges don't overflow */ .fx-version { display: inline-block; From 49d36b6fef7122a448de7136c52e94380204cc97 Mon Sep 17 00:00:00 2001 From: Kelvin-Macapagal Date: Wed, 24 Jun 2026 07:42:51 +0800 Subject: [PATCH 04/13] update links --- src/apisof.net/Shared/MainLayout.razor | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/apisof.net/Shared/MainLayout.razor b/src/apisof.net/Shared/MainLayout.razor index 6ef55ffc..2ff47ffb 100644 --- a/src/apisof.net/Shared/MainLayout.razor +++ b/src/apisof.net/Shared/MainLayout.razor @@ -97,17 +97,14 @@ Consumer Health Privacy
  • - Terms of Use + Terms of Use
  • - Contact Us + Contact Us
  • Hosted on Microsoft Azure
  • -
  • - Advertise with Us -
  • From 2478ea57783b6447e74b4e68e83391c46cd01156 Mon Sep 17 00:00:00 2001 From: Kelvin-Macapagal Date: Thu, 25 Jun 2026 09:15:16 +0800 Subject: [PATCH 05/13] check mark update and remove | --- src/apisof.net/Shared/MainLayout.razor | 2 +- src/apisof.net/appsettings.Development.json | 4 +++- src/apisof.net/wwwroot/css/site.css | 14 +++----------- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/apisof.net/Shared/MainLayout.razor b/src/apisof.net/Shared/MainLayout.razor index 2ff47ffb..e21bdc44 100644 --- a/src/apisof.net/Shared/MainLayout.razor +++ b/src/apisof.net/Shared/MainLayout.razor @@ -114,7 +114,7 @@ - + Your Privacy Choices diff --git a/src/apisof.net/appsettings.Development.json b/src/apisof.net/appsettings.Development.json index 51737579..a2312541 100644 --- a/src/apisof.net/appsettings.Development.json +++ b/src/apisof.net/appsettings.Development.json @@ -6,5 +6,7 @@ "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } - } + }, + "AzureStorageServiceUrl": "https://devstoreaccount1.blob.core.windows.net/", + "ApisOfDotNetWebHookSecret": "dev-webhook-secret" } diff --git a/src/apisof.net/wwwroot/css/site.css b/src/apisof.net/wwwroot/css/site.css index 2cb1c30c..799646a9 100644 --- a/src/apisof.net/wwwroot/css/site.css +++ b/src/apisof.net/wwwroot/css/site.css @@ -662,7 +662,8 @@ body { .uhf-footer-links { display: flex; flex-wrap: wrap; - gap: 0; + column-gap: 0.7rem; + row-gap: 0.25rem; list-style: none; margin: 0; padding: 0; @@ -672,12 +673,6 @@ body { white-space: nowrap; } -.uhf-footer-links li+li::before { - content: "|"; - color: rgba(255, 255, 255, 0.55); - margin: 0 0.55rem; -} - .uhf-footer-links a, .uhf-footer-links a:link, .uhf-footer-links a:visited { @@ -704,13 +699,10 @@ body { /* Small screens (mobile and narrow windows) */ @media (max-width: 480px) { .uhf-footer-links { + column-gap: 0.55rem; row-gap: 0.25rem; } - .uhf-footer-links li+li::before { - margin: 0 0.4rem; - } - /* Container adjustments */ .container-fluid { padding-left: 12px; From 72c1477e80c0dc3afc343d6a05fe998edf2c719b Mon Sep 17 00:00:00 2001 From: Kelvin-Macapagal Date: Thu, 25 Jun 2026 09:16:29 +0800 Subject: [PATCH 06/13] Update appsettings.Development.json --- src/apisof.net/appsettings.Development.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/apisof.net/appsettings.Development.json b/src/apisof.net/appsettings.Development.json index a2312541..51737579 100644 --- a/src/apisof.net/appsettings.Development.json +++ b/src/apisof.net/appsettings.Development.json @@ -6,7 +6,5 @@ "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } - }, - "AzureStorageServiceUrl": "https://devstoreaccount1.blob.core.windows.net/", - "ApisOfDotNetWebHookSecret": "dev-webhook-secret" + } } From 307f609639e1870e07b07d2828be1d6094752969 Mon Sep 17 00:00:00 2001 From: Kelvin-Macapagal Date: Fri, 26 Jun 2026 14:37:55 +0800 Subject: [PATCH 07/13] align manage cookie --- src/apisof.net/wwwroot/css/site.css | 157 +++++++++++++++++++++- src/apisof.net/wwwroot/js/site.js | 198 +++++++++++++++++++++++++++- 2 files changed, 352 insertions(+), 3 deletions(-) diff --git a/src/apisof.net/wwwroot/css/site.css b/src/apisof.net/wwwroot/css/site.css index 799646a9..e0556ef0 100644 --- a/src/apisof.net/wwwroot/css/site.css +++ b/src/apisof.net/wwwroot/css/site.css @@ -769,4 +769,159 @@ body { white-space: normal; word-break: break-word; } -} \ No newline at end of file +} +/* Cookie Preferences Dialog Styles */ +#cookie-preferences-backdrop { + display: none; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + z-index: 1000; +} + +#cookie-preferences-dialog { + display: none; + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: var(--bs-body-bg); + border-radius: 0.375rem; + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); + z-index: 1001; + max-width: 500px; + width: 90%; + max-height: 90vh; + overflow-y: auto; +} + +.cookie-preferences-content { + padding: 1.5rem; +} + +.cookie-preferences-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; + border-bottom: 1px solid var(--bs-border-color); + padding-bottom: 1rem; +} + +#cookie-preferences-title { + margin: 0; + font-size: 1.5rem; + font-weight: 600; +} + +.cookie-preferences-close { + background: none; + border: none; + font-size: 1.5rem; + cursor: pointer; + padding: 0; + margin: 0; + color: inherit; + opacity: 0.7; +} + +.cookie-preferences-close:hover { + opacity: 1; +} + +.cookie-preferences-container { + margin: 1rem 0; +} + +.cookie-preference-section { + margin-bottom: 1rem; + padding: 0.75rem; + border: 1px solid var(--bs-border-color); + border-radius: 0.375rem; +} + +.cookie-preference-label-container { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.cookie-preference-label { + display: flex; + align-items: center; + cursor: pointer; + font-weight: 500; +} + +.cookie-preference-checkbox { + margin-right: 0.75rem; + width: 1rem; + height: 1rem; + cursor: pointer; +} + +.cookie-preference-checkbox:disabled { + cursor: not-allowed; + opacity: 0.7; +} + +.cookie-preference-name { + user-select: none; +} + +.cookie-preference-description { + margin: 0; + font-size: 0.875rem; + color: var(--bs-secondary-color); + margin-left: 2rem; +} + +.cookie-preferences-footer { + display: flex; + gap: 0.75rem; + margin-top: 1.5rem; + padding-top: 1rem; + border-top: 1px solid var(--bs-border-color); + justify-content: flex-end; +} + +.cookie-preferences-button { + padding: 0.5rem 1rem; + border-radius: 0.375rem; + border: 1px solid var(--bs-border-color); + background-color: var(--bs-secondary-bg); + color: var(--bs-body-color); + cursor: pointer; + font-size: 0.875rem; + font-weight: 500; + transition: all 0.2s ease; +} + +.cookie-preferences-button:hover { + background-color: var(--bs-tertiary-bg); +} + +.cookie-preferences-accept, +.cookie-preferences-save { + background-color: var(--dotnet-purple); + color: white; + border-color: var(--dotnet-purple); +} + +.cookie-preferences-accept:hover, +.cookie-preferences-save:hover { + background-color: #6c3fbf; + border-color: #6c3fbf; +} + +.cookie-preferences-reject { + background-color: transparent; +} + +.cookie-preferences-reject:hover { + background-color: var(--bs-danger-bg-subtle); + color: var(--bs-danger); +} diff --git a/src/apisof.net/wwwroot/js/site.js b/src/apisof.net/wwwroot/js/site.js index 00f728ec..c0f6788a 100644 --- a/src/apisof.net/wwwroot/js/site.js +++ b/src/apisof.net/wwwroot/js/site.js @@ -28,9 +28,203 @@ function initializeCookieConsent() { }); } +function createCookiePreferencesControl() { + var control = { + preferencesDialog: null, + backdrop: null, + + createDialog: function() { + var self = this; + + // Create backdrop + this.backdrop = document.createElement('div'); + this.backdrop.id = 'cookie-preferences-backdrop'; + this.backdrop.setAttribute('role', 'presentation'); + + // Create dialog container + this.preferencesDialog = document.createElement('div'); + this.preferencesDialog.id = 'cookie-preferences-dialog'; + this.preferencesDialog.setAttribute('role', 'dialog'); + this.preferencesDialog.setAttribute('aria-labelledby', 'cookie-preferences-title'); + this.preferencesDialog.setAttribute('aria-modal', 'true'); + + // Create dialog content + var content = document.createElement('div'); + content.className = 'cookie-preferences-content'; + + // Header + var header = document.createElement('div'); + header.className = 'cookie-preferences-header'; + var title = document.createElement('h2'); + title.id = 'cookie-preferences-title'; + title.textContent = 'Manage your consent preferences'; + header.appendChild(title); + + // Close button + var closeBtn = document.createElement('button'); + closeBtn.className = 'cookie-preferences-close'; + closeBtn.setAttribute('aria-label', 'Close preferences dialog'); + closeBtn.innerHTML = '×'; + closeBtn.onclick = function() { self.hidePreferences(); }; + header.appendChild(closeBtn); + + content.appendChild(header); + + // Preferences sections + var preferencesContainer = document.createElement('div'); + preferencesContainer.className = 'cookie-preferences-container'; + + var categories = [ + { name: 'Required', category: WcpConsent.consentCategories.Required, description: 'Essential for website functionality' }, + { name: 'Analytics', category: WcpConsent.consentCategories.Analytics, description: 'Help us understand how you use our site' }, + { name: 'Social Media', category: WcpConsent.consentCategories.SocialMedia, description: 'Enable social media features' }, + { name: 'Advertising', category: WcpConsent.consentCategories.Advertising, description: 'Personalized advertising' } + ]; + + categories.forEach(function(cat) { + var section = document.createElement('div'); + section.className = 'cookie-preference-section'; + + var labelContainer = document.createElement('div'); + labelContainer.className = 'cookie-preference-label-container'; + + var label = document.createElement('label'); + label.className = 'cookie-preference-label'; + + var checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.className = 'cookie-preference-checkbox'; + checkbox.dataset.category = cat.name; + if (cat.name === 'Required') { + checkbox.disabled = true; + checkbox.checked = true; + } + + var labelText = document.createElement('span'); + labelText.className = 'cookie-preference-name'; + labelText.textContent = cat.name; + + label.appendChild(checkbox); + label.appendChild(labelText); + + var description = document.createElement('p'); + description.className = 'cookie-preference-description'; + description.textContent = cat.description; + + labelContainer.appendChild(label); + labelContainer.appendChild(description); + + section.appendChild(labelContainer); + preferencesContainer.appendChild(section); + }); + + content.appendChild(preferencesContainer); + + // Footer with buttons + var footer = document.createElement('div'); + footer.className = 'cookie-preferences-footer'; + + var rejectBtn = document.createElement('button'); + rejectBtn.className = 'cookie-preferences-button cookie-preferences-reject'; + rejectBtn.textContent = 'Reject All'; + rejectBtn.onclick = function() { self.rejectAll(); }; + + var acceptBtn = document.createElement('button'); + acceptBtn.className = 'cookie-preferences-button cookie-preferences-accept'; + acceptBtn.textContent = 'Accept All'; + acceptBtn.onclick = function() { self.acceptAll(); }; + + var saveBtn = document.createElement('button'); + saveBtn.className = 'cookie-preferences-button cookie-preferences-save'; + saveBtn.textContent = 'Save Preferences'; + saveBtn.onclick = function() { self.savePreferences(); }; + + footer.appendChild(rejectBtn); + footer.appendChild(acceptBtn); + footer.appendChild(saveBtn); + + content.appendChild(footer); + this.preferencesDialog.appendChild(content); + + // Add to body + document.body.appendChild(this.backdrop); + document.body.appendChild(this.preferencesDialog); + + // Handle escape key + document.addEventListener('keydown', function(e) { + if (e.key === 'Escape' && self.preferencesDialog && self.preferencesDialog.style.display !== 'none') { + self.hidePreferences(); + } + }); + }, + + showPreferences: function() { + if (!this.preferencesDialog) { + this.createDialog(); + } + this.backdrop.style.display = 'block'; + this.preferencesDialog.style.display = 'block'; + // Load current preferences + this.loadPreferences(); + }, + + hidePreferences: function() { + if (this.backdrop) this.backdrop.style.display = 'none'; + if (this.preferencesDialog) this.preferencesDialog.style.display = 'none'; + }, + + loadPreferences: function() { + if (!siteConsent) return; + var checkboxes = document.querySelectorAll('.cookie-preference-checkbox'); + checkboxes.forEach(function(checkbox) { + var category = checkbox.dataset.category; + if (category === 'Required') { + checkbox.checked = true; + } else { + checkbox.checked = siteConsent.getConsentFor(WcpConsent.consentCategories[category]); + } + }); + }, + + acceptAll: function() { + if (!siteConsent) return; + siteConsent.setConsent(true); + this.hidePreferences(); + }, + + rejectAll: function() { + if (!siteConsent) return; + var preferences = { + Required: true, + Analytics: false, + SocialMedia: false, + Advertising: false + }; + siteConsent.setConsent(preferences); + this.hidePreferences(); + }, + + savePreferences: function() { + if (!siteConsent) return; + var preferences = {}; + var checkboxes = document.querySelectorAll('.cookie-preference-checkbox'); + checkboxes.forEach(function(checkbox) { + preferences[checkbox.dataset.category] = checkbox.checked; + }); + siteConsent.setConsent(preferences); + this.hidePreferences(); + } + }; + + return control; +} + function manageConsent() { - if (siteConsent && typeof siteConsent.manageConsent === "function") { - siteConsent.manageConsent(); + if (typeof window.cookiePreferencesControl === 'undefined') { + window.cookiePreferencesControl = createCookiePreferencesControl(); + } + if (window.cookiePreferencesControl) { + window.cookiePreferencesControl.showPreferences(); } } From 250142be46431397892f530373e3abd40b44d82b Mon Sep 17 00:00:00 2001 From: Kelvin-Macapagal Date: Sat, 27 Jun 2026 06:09:51 +0800 Subject: [PATCH 08/13] remove manually usage apply wcp api script --- src/apisof.net/wwwroot/css/site.css | 155 ---------------------- src/apisof.net/wwwroot/js/site.js | 198 +--------------------------- 2 files changed, 2 insertions(+), 351 deletions(-) diff --git a/src/apisof.net/wwwroot/css/site.css b/src/apisof.net/wwwroot/css/site.css index e0556ef0..14ed8ac7 100644 --- a/src/apisof.net/wwwroot/css/site.css +++ b/src/apisof.net/wwwroot/css/site.css @@ -770,158 +770,3 @@ body { word-break: break-word; } } -/* Cookie Preferences Dialog Styles */ -#cookie-preferences-backdrop { - display: none; - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.5); - z-index: 1000; -} - -#cookie-preferences-dialog { - display: none; - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - background-color: var(--bs-body-bg); - border-radius: 0.375rem; - box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); - z-index: 1001; - max-width: 500px; - width: 90%; - max-height: 90vh; - overflow-y: auto; -} - -.cookie-preferences-content { - padding: 1.5rem; -} - -.cookie-preferences-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 1rem; - border-bottom: 1px solid var(--bs-border-color); - padding-bottom: 1rem; -} - -#cookie-preferences-title { - margin: 0; - font-size: 1.5rem; - font-weight: 600; -} - -.cookie-preferences-close { - background: none; - border: none; - font-size: 1.5rem; - cursor: pointer; - padding: 0; - margin: 0; - color: inherit; - opacity: 0.7; -} - -.cookie-preferences-close:hover { - opacity: 1; -} - -.cookie-preferences-container { - margin: 1rem 0; -} - -.cookie-preference-section { - margin-bottom: 1rem; - padding: 0.75rem; - border: 1px solid var(--bs-border-color); - border-radius: 0.375rem; -} - -.cookie-preference-label-container { - display: flex; - flex-direction: column; - gap: 0.5rem; -} - -.cookie-preference-label { - display: flex; - align-items: center; - cursor: pointer; - font-weight: 500; -} - -.cookie-preference-checkbox { - margin-right: 0.75rem; - width: 1rem; - height: 1rem; - cursor: pointer; -} - -.cookie-preference-checkbox:disabled { - cursor: not-allowed; - opacity: 0.7; -} - -.cookie-preference-name { - user-select: none; -} - -.cookie-preference-description { - margin: 0; - font-size: 0.875rem; - color: var(--bs-secondary-color); - margin-left: 2rem; -} - -.cookie-preferences-footer { - display: flex; - gap: 0.75rem; - margin-top: 1.5rem; - padding-top: 1rem; - border-top: 1px solid var(--bs-border-color); - justify-content: flex-end; -} - -.cookie-preferences-button { - padding: 0.5rem 1rem; - border-radius: 0.375rem; - border: 1px solid var(--bs-border-color); - background-color: var(--bs-secondary-bg); - color: var(--bs-body-color); - cursor: pointer; - font-size: 0.875rem; - font-weight: 500; - transition: all 0.2s ease; -} - -.cookie-preferences-button:hover { - background-color: var(--bs-tertiary-bg); -} - -.cookie-preferences-accept, -.cookie-preferences-save { - background-color: var(--dotnet-purple); - color: white; - border-color: var(--dotnet-purple); -} - -.cookie-preferences-accept:hover, -.cookie-preferences-save:hover { - background-color: #6c3fbf; - border-color: #6c3fbf; -} - -.cookie-preferences-reject { - background-color: transparent; -} - -.cookie-preferences-reject:hover { - background-color: var(--bs-danger-bg-subtle); - color: var(--bs-danger); -} diff --git a/src/apisof.net/wwwroot/js/site.js b/src/apisof.net/wwwroot/js/site.js index c0f6788a..5e4e229d 100644 --- a/src/apisof.net/wwwroot/js/site.js +++ b/src/apisof.net/wwwroot/js/site.js @@ -28,203 +28,9 @@ function initializeCookieConsent() { }); } -function createCookiePreferencesControl() { - var control = { - preferencesDialog: null, - backdrop: null, - - createDialog: function() { - var self = this; - - // Create backdrop - this.backdrop = document.createElement('div'); - this.backdrop.id = 'cookie-preferences-backdrop'; - this.backdrop.setAttribute('role', 'presentation'); - - // Create dialog container - this.preferencesDialog = document.createElement('div'); - this.preferencesDialog.id = 'cookie-preferences-dialog'; - this.preferencesDialog.setAttribute('role', 'dialog'); - this.preferencesDialog.setAttribute('aria-labelledby', 'cookie-preferences-title'); - this.preferencesDialog.setAttribute('aria-modal', 'true'); - - // Create dialog content - var content = document.createElement('div'); - content.className = 'cookie-preferences-content'; - - // Header - var header = document.createElement('div'); - header.className = 'cookie-preferences-header'; - var title = document.createElement('h2'); - title.id = 'cookie-preferences-title'; - title.textContent = 'Manage your consent preferences'; - header.appendChild(title); - - // Close button - var closeBtn = document.createElement('button'); - closeBtn.className = 'cookie-preferences-close'; - closeBtn.setAttribute('aria-label', 'Close preferences dialog'); - closeBtn.innerHTML = '×'; - closeBtn.onclick = function() { self.hidePreferences(); }; - header.appendChild(closeBtn); - - content.appendChild(header); - - // Preferences sections - var preferencesContainer = document.createElement('div'); - preferencesContainer.className = 'cookie-preferences-container'; - - var categories = [ - { name: 'Required', category: WcpConsent.consentCategories.Required, description: 'Essential for website functionality' }, - { name: 'Analytics', category: WcpConsent.consentCategories.Analytics, description: 'Help us understand how you use our site' }, - { name: 'Social Media', category: WcpConsent.consentCategories.SocialMedia, description: 'Enable social media features' }, - { name: 'Advertising', category: WcpConsent.consentCategories.Advertising, description: 'Personalized advertising' } - ]; - - categories.forEach(function(cat) { - var section = document.createElement('div'); - section.className = 'cookie-preference-section'; - - var labelContainer = document.createElement('div'); - labelContainer.className = 'cookie-preference-label-container'; - - var label = document.createElement('label'); - label.className = 'cookie-preference-label'; - - var checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.className = 'cookie-preference-checkbox'; - checkbox.dataset.category = cat.name; - if (cat.name === 'Required') { - checkbox.disabled = true; - checkbox.checked = true; - } - - var labelText = document.createElement('span'); - labelText.className = 'cookie-preference-name'; - labelText.textContent = cat.name; - - label.appendChild(checkbox); - label.appendChild(labelText); - - var description = document.createElement('p'); - description.className = 'cookie-preference-description'; - description.textContent = cat.description; - - labelContainer.appendChild(label); - labelContainer.appendChild(description); - - section.appendChild(labelContainer); - preferencesContainer.appendChild(section); - }); - - content.appendChild(preferencesContainer); - - // Footer with buttons - var footer = document.createElement('div'); - footer.className = 'cookie-preferences-footer'; - - var rejectBtn = document.createElement('button'); - rejectBtn.className = 'cookie-preferences-button cookie-preferences-reject'; - rejectBtn.textContent = 'Reject All'; - rejectBtn.onclick = function() { self.rejectAll(); }; - - var acceptBtn = document.createElement('button'); - acceptBtn.className = 'cookie-preferences-button cookie-preferences-accept'; - acceptBtn.textContent = 'Accept All'; - acceptBtn.onclick = function() { self.acceptAll(); }; - - var saveBtn = document.createElement('button'); - saveBtn.className = 'cookie-preferences-button cookie-preferences-save'; - saveBtn.textContent = 'Save Preferences'; - saveBtn.onclick = function() { self.savePreferences(); }; - - footer.appendChild(rejectBtn); - footer.appendChild(acceptBtn); - footer.appendChild(saveBtn); - - content.appendChild(footer); - this.preferencesDialog.appendChild(content); - - // Add to body - document.body.appendChild(this.backdrop); - document.body.appendChild(this.preferencesDialog); - - // Handle escape key - document.addEventListener('keydown', function(e) { - if (e.key === 'Escape' && self.preferencesDialog && self.preferencesDialog.style.display !== 'none') { - self.hidePreferences(); - } - }); - }, - - showPreferences: function() { - if (!this.preferencesDialog) { - this.createDialog(); - } - this.backdrop.style.display = 'block'; - this.preferencesDialog.style.display = 'block'; - // Load current preferences - this.loadPreferences(); - }, - - hidePreferences: function() { - if (this.backdrop) this.backdrop.style.display = 'none'; - if (this.preferencesDialog) this.preferencesDialog.style.display = 'none'; - }, - - loadPreferences: function() { - if (!siteConsent) return; - var checkboxes = document.querySelectorAll('.cookie-preference-checkbox'); - checkboxes.forEach(function(checkbox) { - var category = checkbox.dataset.category; - if (category === 'Required') { - checkbox.checked = true; - } else { - checkbox.checked = siteConsent.getConsentFor(WcpConsent.consentCategories[category]); - } - }); - }, - - acceptAll: function() { - if (!siteConsent) return; - siteConsent.setConsent(true); - this.hidePreferences(); - }, - - rejectAll: function() { - if (!siteConsent) return; - var preferences = { - Required: true, - Analytics: false, - SocialMedia: false, - Advertising: false - }; - siteConsent.setConsent(preferences); - this.hidePreferences(); - }, - - savePreferences: function() { - if (!siteConsent) return; - var preferences = {}; - var checkboxes = document.querySelectorAll('.cookie-preference-checkbox'); - checkboxes.forEach(function(checkbox) { - preferences[checkbox.dataset.category] = checkbox.checked; - }); - siteConsent.setConsent(preferences); - this.hidePreferences(); - } - }; - - return control; -} - function manageConsent() { - if (typeof window.cookiePreferencesControl === 'undefined') { - window.cookiePreferencesControl = createCookiePreferencesControl(); - } - if (window.cookiePreferencesControl) { - window.cookiePreferencesControl.showPreferences(); + if (siteConsent && siteConsent.isConsentRequired && typeof siteConsent.manageConsent === "function") { + siteConsent.manageConsent(); } } From dbdea23dad05743c68f44157beb1b0a0024e0f80 Mon Sep 17 00:00:00 2001 From: Kelvin-Macapagal Date: Sat, 27 Jun 2026 06:37:55 +0800 Subject: [PATCH 09/13] initialized instance or falls back to WcpConsent.siteConsent --- src/apisof.net/Shared/MainLayout.razor | 2 +- src/apisof.net/wwwroot/js/site.js | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/apisof.net/Shared/MainLayout.razor b/src/apisof.net/Shared/MainLayout.razor index e21bdc44..d439777b 100644 --- a/src/apisof.net/Shared/MainLayout.razor +++ b/src/apisof.net/Shared/MainLayout.razor @@ -106,7 +106,7 @@ Hosted on Microsoft Azure
  • diff --git a/src/apisof.net/wwwroot/js/site.js b/src/apisof.net/wwwroot/js/site.js index 5e4e229d..da20a8a7 100644 --- a/src/apisof.net/wwwroot/js/site.js +++ b/src/apisof.net/wwwroot/js/site.js @@ -28,12 +28,15 @@ function initializeCookieConsent() { }); } -function manageConsent() { - if (siteConsent && siteConsent.isConsentRequired && typeof siteConsent.manageConsent === "function") { - siteConsent.manageConsent(); +function openCookiePreferences() { + var consent = siteConsent || (typeof WcpConsent !== "undefined" ? WcpConsent.siteConsent : null); + if (consent && typeof consent.manageConsent === "function") { + consent.manageConsent(); } } +window.openCookiePreferences = openCookiePreferences; + if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", initializeCookieConsent); } else { From 3a2a472db99aee08c0769a3ff8ec97ed01290e41 Mon Sep 17 00:00:00 2001 From: Kelvin-Macapagal Date: Sat, 27 Jun 2026 07:11:59 +0800 Subject: [PATCH 10/13] remove hard coded display none --- src/apisof.net/Shared/MainLayout.razor | 2 +- src/apisof.net/wwwroot/js/site.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apisof.net/Shared/MainLayout.razor b/src/apisof.net/Shared/MainLayout.razor index d439777b..d41cce71 100644 --- a/src/apisof.net/Shared/MainLayout.razor +++ b/src/apisof.net/Shared/MainLayout.razor @@ -105,7 +105,7 @@
  • Hosted on Microsoft Azure
  • -
  • diff --git a/src/apisof.net/wwwroot/js/site.js b/src/apisof.net/wwwroot/js/site.js index da20a8a7..a4d6ec0c 100644 --- a/src/apisof.net/wwwroot/js/site.js +++ b/src/apisof.net/wwwroot/js/site.js @@ -3,6 +3,7 @@ var siteConsent = null; function setCookieManagementVisibility(isVisible) { var elements = document.querySelectorAll(".manageCookieChoice"); for (var i = 0; i < elements.length; i++) { + elements[i].hidden = !isVisible; elements[i].style.display = isVisible ? "list-item" : "none"; } } From 827949b4c3e5e49f39863d3e398451265e5856be Mon Sep 17 00:00:00 2001 From: Kelvin-Macapagal Date: Sat, 27 Jun 2026 07:25:20 +0800 Subject: [PATCH 11/13] align logic --- src/apisof.net/Shared/MainLayout.razor | 2 +- src/apisof.net/wwwroot/js/site.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/apisof.net/Shared/MainLayout.razor b/src/apisof.net/Shared/MainLayout.razor index d41cce71..d439777b 100644 --- a/src/apisof.net/Shared/MainLayout.razor +++ b/src/apisof.net/Shared/MainLayout.razor @@ -105,7 +105,7 @@
  • Hosted on Microsoft Azure
  • -
  • diff --git a/src/apisof.net/wwwroot/js/site.js b/src/apisof.net/wwwroot/js/site.js index a4d6ec0c..fe9d2a08 100644 --- a/src/apisof.net/wwwroot/js/site.js +++ b/src/apisof.net/wwwroot/js/site.js @@ -3,8 +3,7 @@ var siteConsent = null; function setCookieManagementVisibility(isVisible) { var elements = document.querySelectorAll(".manageCookieChoice"); for (var i = 0; i < elements.length; i++) { - elements[i].hidden = !isVisible; - elements[i].style.display = isVisible ? "list-item" : "none"; + elements[i].style.display = isVisible ? "inline-block" : "none"; } } From 0c69dfed4babae827f718cc03b9687c852dc659a Mon Sep 17 00:00:00 2001 From: Kelvin-Macapagal Date: Sun, 28 Jun 2026 19:43:24 +0800 Subject: [PATCH 12/13] add logic to observer --- src/apisof.net/wwwroot/js/site.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/apisof.net/wwwroot/js/site.js b/src/apisof.net/wwwroot/js/site.js index fe9d2a08..8d8f3703 100644 --- a/src/apisof.net/wwwroot/js/site.js +++ b/src/apisof.net/wwwroot/js/site.js @@ -2,8 +2,11 @@ var siteConsent = null; function setCookieManagementVisibility(isVisible) { var elements = document.querySelectorAll(".manageCookieChoice"); + var targetDisplay = isVisible ? "inline-block" : "none"; for (var i = 0; i < elements.length; i++) { - elements[i].style.display = isVisible ? "inline-block" : "none"; + if (elements[i].style.display !== targetDisplay) { + elements[i].style.display = targetDisplay; + } } } @@ -52,6 +55,10 @@ function scrollIntoMainContent() { } var observer = new MutationObserver(function () { + if (siteConsent) { + setCookieManagementVisibility(!!siteConsent.isConsentRequired); + } + $('[data-toggle="popover"]').popover({ placement: 'top', trigger: 'hover', From 181c00d96805e45908e0634d629d1f00a0aea8c5 Mon Sep 17 00:00:00 2001 From: Dan Zhu <33338258+danzhu54@users.noreply.github.com> Date: Tue, 30 Jun 2026 12:39:39 -0700 Subject: [PATCH 13/13] Wrap site.js in an IIFE to avoid leaking globals Encapsulate site.js in an IIFE so internal helpers (siteConsent, setCookieManagementVisibility, initializeCookieConsent, scrollIntoMainContent, observer) no longer leak onto window and risk name collisions. openCookiePreferences is still explicitly exported via window.openCookiePreferences since it is invoked from the footer "Manage cookies" link. Also adds "use strict". --- src/apisof.net/wwwroot/js/site.js | 141 ++++++++++++++++-------------- 1 file changed, 73 insertions(+), 68 deletions(-) diff --git a/src/apisof.net/wwwroot/js/site.js b/src/apisof.net/wwwroot/js/site.js index 8d8f3703..a33da6da 100644 --- a/src/apisof.net/wwwroot/js/site.js +++ b/src/apisof.net/wwwroot/js/site.js @@ -1,89 +1,94 @@ -var siteConsent = null; +(function () { + "use strict"; -function setCookieManagementVisibility(isVisible) { - var elements = document.querySelectorAll(".manageCookieChoice"); - var targetDisplay = isVisible ? "inline-block" : "none"; - for (var i = 0; i < elements.length; i++) { - if (elements[i].style.display !== targetDisplay) { - elements[i].style.display = targetDisplay; - } - } -} + var siteConsent = null; -function initializeCookieConsent() { - if (typeof WcpConsent === "undefined" || typeof WcpConsent.init !== "function") { - return; + function setCookieManagementVisibility(isVisible) { + var elements = document.querySelectorAll(".manageCookieChoice"); + var targetDisplay = isVisible ? "inline-block" : "none"; + for (var i = 0; i < elements.length; i++) { + if (elements[i].style.display !== targetDisplay) { + elements[i].style.display = targetDisplay; + } + } } - WcpConsent.init("en-US", "cookie-banner", function (err, consentInstance) { - if (err || !consentInstance) { + function initializeCookieConsent() { + if (typeof WcpConsent === "undefined" || typeof WcpConsent.init !== "function") { return; } - siteConsent = consentInstance; - setCookieManagementVisibility(!!siteConsent.isConsentRequired); + WcpConsent.init("en-US", "cookie-banner", function (err, consentInstance) { + if (err || !consentInstance) { + return; + } - if (typeof siteConsent.onConsentChanged === "function") { - siteConsent.onConsentChanged(function () { - setCookieManagementVisibility(!!siteConsent.isConsentRequired); - }); - } - }); -} + siteConsent = consentInstance; + setCookieManagementVisibility(!!siteConsent.isConsentRequired); -function openCookiePreferences() { - var consent = siteConsent || (typeof WcpConsent !== "undefined" ? WcpConsent.siteConsent : null); - if (consent && typeof consent.manageConsent === "function") { - consent.manageConsent(); + if (typeof siteConsent.onConsentChanged === "function") { + siteConsent.onConsentChanged(function () { + setCookieManagementVisibility(!!siteConsent.isConsentRequired); + }); + } + }); } -} -window.openCookiePreferences = openCookiePreferences; + function openCookiePreferences() { + var consent = siteConsent || (typeof WcpConsent !== "undefined" ? WcpConsent.siteConsent : null); + if (consent && typeof consent.manageConsent === "function") { + consent.manageConsent(); + } + } -if (document.readyState === "loading") { - document.addEventListener("DOMContentLoaded", initializeCookieConsent); -} else { - initializeCookieConsent(); -} + // Must stay global: invoked from the footer "Manage cookies" link + window.openCookiePreferences = openCookiePreferences; -function scrollIntoMainContent() { - var mainContent = document.getElementById("main-content"); - if (mainContent) { - mainContent.scrollIntoView({ behavior: "smooth" }); - mainContent.focus(); + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", initializeCookieConsent); + } else { + initializeCookieConsent(); } -} -var observer = new MutationObserver(function () { - if (siteConsent) { - setCookieManagementVisibility(!!siteConsent.isConsentRequired); + function scrollIntoMainContent() { + var mainContent = document.getElementById("main-content"); + if (mainContent) { + mainContent.scrollIntoView({ behavior: "smooth" }); + mainContent.focus(); + } } - $('[data-toggle="popover"]').popover({ - placement: 'top', - trigger: 'hover', - boundary: 'body' - }); - $('[data-toggle="popover"]').on('click', function () { - $('[data-toggle="popover"]').popover('dispose'); - }); - $('.search-result-row.selected').each(function () { - this.scrollIntoView({ block: "nearest" }); - }); - $("#skipToMain").on('keydown', function (e) { - if (e.key === "Enter" || e.key === " ") { + var observer = new MutationObserver(function () { + if (siteConsent) { + setCookieManagementVisibility(!!siteConsent.isConsentRequired); + } + + $('[data-toggle="popover"]').popover({ + placement: 'top', + trigger: 'hover', + boundary: 'body' + }); + $('[data-toggle="popover"]').on('click', function () { + $('[data-toggle="popover"]').popover('dispose'); + }); + $('.search-result-row.selected').each(function () { + this.scrollIntoView({ block: "nearest" }); + }); + $("#skipToMain").on('keydown', function (e) { + if (e.key === "Enter" || e.key === " ") { + scrollIntoMainContent(); + e.preventDefault(); + } + }); + $("#skipToMain").on('click', function (e) { scrollIntoMainContent(); e.preventDefault(); - } + }); }); - $("#skipToMain").on('click', function (e) { - scrollIntoMainContent(); - e.preventDefault(); - }); -}); -observer.observe(document, { - subtree: true, - childList: true, - attributes: true -}); + observer.observe(document, { + subtree: true, + childList: true, + attributes: true + }); +})();