diff --git a/media/js/firefox/all/all-init.es6.js b/media/js/firefox/all/all-init.es6.js index 8f52040b5..55ed81993 100644 --- a/media/js/firefox/all/all-init.es6.js +++ b/media/js/firefox/all/all-init.es6.js @@ -8,7 +8,12 @@ import TrackProductDownload from '../../base/datalayer-productdownload.es6'; import MzpModal from '@mozilla-protocol/core/protocol/js/modal'; (function (Mozilla) { - function onLoad() { + // Getter function since outerHTML replacement in fetchContent breaks existing references + function getPartialTargetElement() { + return document.getElementById('partial-target'); + } + + function setUpPartialContentListeners() { const browserHelpContent = document.getElementById('browser-help'); const browserHelpIcon = document.getElementById('icon-browser-help'); const installerHelpContent = document.getElementById('installer-help'); @@ -16,7 +21,6 @@ import MzpModal from '@mozilla-protocol/core/protocol/js/modal'; '.icon-installer-help' ); const downloadButtons = document.querySelectorAll('.download-link'); - function showHelpModal(modalContent, modalTitle, eventLabel) { MzpModal.createModal(this, modalContent, { title: modalTitle, @@ -67,7 +71,6 @@ import MzpModal from '@mozilla-protocol/core/protocol/js/modal'; ); } } - // event tracking for GA4 if (downloadButtons) { for (let i = 0; i < downloadButtons.length; ++i) { @@ -81,6 +84,74 @@ import MzpModal from '@mozilla-protocol/core/protocol/js/modal'; ); } } + + // Override click events for drill-down links. + getPartialTargetElement().addEventListener('click', function (event) { + const anchor = event.target.closest('a'); + if (anchor && anchor.matches('.load-content-partial')) { + event.preventDefault(); + fetchContent(anchor.href, true); + } + }); + } + + // A fetch helper since we use this in both the on click and popstate. + // pushState is a boolean so we avoid pushing state if triggered from popstate. + function fetchContent(url, pushState = false) { + fetch(url, { + // Signifies to backend to return partial HTML. + headers: { 'X-Requested-With': 'XMLHttpRequest' }, + // Ignore what's cached and also don't cache this response. + // This is so we don't get full html pages when we expect partial html, or vice versa. + cache: 'no-store' + }) + .then((response) => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.text(); + }) + .then((html) => { + const partialTarget = getPartialTargetElement(); + partialTarget.outerHTML = html; + + // Re-attach listeners as we just replaced partialTarget + setUpPartialContentListeners(); + + if (pushState) { + history.pushState({ path: url }, '', url); + } + + const activeHeaders = document.querySelectorAll( + '.c-step-name:not(.t-step-disabled)' + ); + const targetHeader = activeHeaders[activeHeaders.length - 1]; + targetHeader.focus({ preventScroll: true }); + }) + .catch((error) => { + throw new Error( + 'There was a problem with the fetch operation:', + error + ); + }); + } + + function onLoad() { + setUpPartialContentListeners(); + + // Add popstate listener so we return partial HTML with browser back button. + window.addEventListener('popstate', function (event) { + if (!event.state) { + return; + } + fetchContent(event.state.path, false); + }); + + // Ensure initial state is set up when the page loads so root page is in popstate. + window.addEventListener('DOMContentLoaded', () => { + const url = window.location.href; + history.replaceState({ path: url }, '', url); + }); } Mozilla.run(onLoad); diff --git a/springfield/firefox/templates/firefox/all/base.html b/springfield/firefox/templates/firefox/all/base.html index b62659585..829268804 100644 --- a/springfield/firefox/templates/firefox/all/base.html +++ b/springfield/firefox/templates/firefox/all/base.html @@ -10,10 +10,6 @@ {{ ftl('firefox-all-download-the-firefox-v2') }} {%- endblock -%} -{%- block page_desc -%} - {{ ftl('firefox-all-everyone-deserves-access-v2') }} -{%- endblock -%} - {% block page_css %} {{ css_bundle('firefox_all') }} {% endblock %} @@ -46,95 +42,7 @@ {% endif %} {% block content %} -
-
-
-
-

{{ ftl('firefox-all-choose-which-firefox') }}

-

{{ self.page_desc() }}

- {% if product %} - {% if product.slug == "desktop-release" %} -
- -
- {% elif product.slug == "desktop-beta" %} -
- -
- {% elif product.slug == "desktop-developer" %} -
- -
- {% elif product.slug == "desktop-nightly" %} -
- -
- {% elif product.slug == "desktop-esr" %} -
- -
- {% elif product.slug == "android-beta" %} -
- -
- {% elif product.slug in ["mobile-release", "android-release", "ios-release"] %} -
- {% if product.slug in ["android-release", "mobile-release"] %} - Android: - - {% endif %} - {% if product.slug in ["ios-release", "mobile-release"] %} - iOS: - - {% endif %} -
- {% endif %} - {% endif %} - -
-
- {% include 'firefox/all/product.html' %} - {% include 'firefox/all/platform.html' %} - {% include 'firefox/all/lang.html' %} - {% include 'firefox/all/download.html' %} -
-
-
-
+ {% include 'firefox/all/includes/main.html' %} {% endblock %} {% block js %} diff --git a/springfield/firefox/templates/firefox/all/download.html b/springfield/firefox/templates/firefox/all/download.html index 8d74c4e12..58efdfe18 100644 --- a/springfield/firefox/templates/firefox/all/download.html +++ b/springfield/firefox/templates/firefox/all/download.html @@ -9,7 +9,7 @@ {% set icon_download ='' %} {# Show download #} -

+

{{ ftl('firefox-all-download') }} {% if product and platform and locale %} {{ ftl('firefox-all-down-arrow') }} diff --git a/springfield/firefox/templates/firefox/all/includes/main.html b/springfield/firefox/templates/firefox/all/includes/main.html new file mode 100644 index 000000000..0cf6df652 --- /dev/null +++ b/springfield/firefox/templates/firefox/all/includes/main.html @@ -0,0 +1,95 @@ +{# + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. +#} + +
+
+
+
+

{{ ftl('firefox-all-choose-which-firefox') }}

+

{{ ftl('firefox-all-everyone-deserves-access-v2') }}

+ {% if product %} + {% if product.slug == "desktop-release" %} + + {% elif product.slug == "desktop-beta" %} + + {% elif product.slug == "desktop-developer" %} + + {% elif product.slug == "desktop-nightly" %} + + {% elif product.slug == "desktop-esr" %} + + {% elif product.slug == "android-beta" %} + + {% elif product.slug in ["mobile-release", "android-release", "ios-release"] %} +
+ {% if product.slug in ["android-release", "mobile-release"] %} + Android: + + {% endif %} + {% if product.slug in ["ios-release", "mobile-release"] %} + iOS: + + {% endif %} +
+ {% endif %} + {% endif %} + +
+
+ {% include 'firefox/all/product.html' %} + {% include 'firefox/all/platform.html' %} + {% include 'firefox/all/lang.html' %} + {% include 'firefox/all/download.html' %} +
+
+
+
diff --git a/springfield/firefox/templates/firefox/all/lang.html b/springfield/firefox/templates/firefox/all/lang.html index ba113a4c8..f45b6c414 100644 --- a/springfield/firefox/templates/firefox/all/lang.html +++ b/springfield/firefox/templates/firefox/all/lang.html @@ -5,12 +5,12 @@ #} {# Choose language #} -

+

{{ ftl('firefox-all-language-v2') }} {% if product and platform and locale %} {{ locale_name }} {% if product.slug.startswith('desktop') and platform != "win-store" %} - {{ ftl('firefox-all-change-language') }} + {{ ftl('firefox-all-change-language') }} {% endif %} {% elif product and platform %} {{ ftl('firefox-all-down-arrow') }} @@ -24,7 +24,7 @@

{{ ftl('firefox-all-select-your-preferred-language') }}{{ ftl('firefox-all-down-arrow') }}

diff --git a/springfield/firefox/templates/firefox/all/platform.html b/springfield/firefox/templates/firefox/all/platform.html index 675199aad..9d246cd1d 100644 --- a/springfield/firefox/templates/firefox/all/platform.html +++ b/springfield/firefox/templates/firefox/all/platform.html @@ -7,12 +7,12 @@ {# Choose platform #} -

+

{{ ftl('firefox-all-platform-v2') }} {% if product and platform %} {{ platform_name }} {% if product.slug.startswith('desktop') %} - {{ ftl('firefox-all-change-platform') }} + {{ ftl('firefox-all-change-platform') }} {% endif %} {% elif product %} {{ ftl('firefox-all-down-arrow') }} @@ -31,7 +31,7 @@

diff --git a/springfield/firefox/templates/firefox/all/product.html b/springfield/firefox/templates/firefox/all/product.html index acb61a4af..1435af74d 100644 --- a/springfield/firefox/templates/firefox/all/product.html +++ b/springfield/firefox/templates/firefox/all/product.html @@ -6,10 +6,10 @@ {# Choose product #} -

+

{{ ftl('firefox-all-browser-v2') }} {% if product %} - {{ product and product.name }} {{ ftl('firefox-all-change-browser') }} + {{ product and product.name }} {{ ftl('firefox-all-change-browser') }} {% else %} {{ ftl('firefox-all-down-arrow') }} {% endif %} @@ -25,10 +25,10 @@

{{ ftl('firefox-all-desktop') }}

@@ -36,10 +36,10 @@

{{ ftl('firefox-all-mobile') }}

    -
  • {{ ftl('firefox-all-product-firefox') }} {{ ftl('firefox-all-recommended') }}
  • +
  • {{ ftl('firefox-all-product-firefox') }} {{ ftl('firefox-all-recommended') }}
  • {% for p in products %} {% if p.slug.startswith('android') and not p.slug.endswith('release')%} -
  • {{ p.name }}
  • +
  • {{ p.name }}
  • {% endif %} {% endfor %}
  • {{ ftl('firefox-all-product-firefox-ios-testflight') }}
  • diff --git a/springfield/firefox/views.py b/springfield/firefox/views.py index a76b5fc2b..2ba096556 100644 --- a/springfield/firefox/views.py +++ b/springfield/firefox/views.py @@ -272,7 +272,11 @@ class MobileRelease: platform_name = None locale_name = None download_url = None - template_name = "firefox/all/base.html" + if request.headers.get("X-Requested-With") == "XMLHttpRequest": + template_name = "firefox/all/includes/main.html" + else: + template_name = "firefox/all/base.html" + lang_multi = ftl("firefox-all-lang-multi", ftl_files=ftl_files) if product: