{% extends "!layout.html" %}

{% block header %}
{%- if outdated %}
<div id="outdated-warning" style="padding: .5em; text-align: center; background-color: #FFBABA; color: #6A0E0E;">
    {% trans %}This document is for an old version of Python that is no longer supported.
    You should upgrade, and read the{% endtrans %}
    <a href="/3/{{ pagename }}{{ file_suffix }}">{% trans %}Python documentation for the current stable release{% endtrans %}</a>.
</div>
{%- endif %}

{%- if is_deployment_preview %}
<div id="deployment-preview-warning" style="padding: .5em; text-align: center; background-color: #fff2ba; color: #6a580e;">
  {% trans %}This is a deploy preview created from a <a href="{{ repository_url }}/pull/{{ pr_id }}">pull request</a>.
  For authoritative documentation, see{% endtrans %}
  <a href="https://docs.python.org/3/{{ pagename }}{{ file_suffix }}">{% trans %}the current stable release{% endtrans %}</a>.
</div>
{%- endif %}
{% endblock %}

{% block rootrellink %}
{{ super() }}
    <li id="cpython-language-and-version">
      <a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}
    </li>
{% endblock %}

{% block extrahead %}
    <link rel="canonical" href="https://docs.python.org/3/{{pagename}}.html" />
    {% if builder != "htmlhelp" %}
      {% if pagename == 'whatsnew/changelog' and not embedded %}
      <script type="text/javascript" src="{{ pathto('_static/changelog_search.js', 1) }}"></script>{% endif %}
    {% endif %}

    {# custom CSS; used in asyncio docs! #}
    <style>
      @media only screen {{ "{" }}
        table.full-width-table {{ "{" }}
            width: 100%;
        {{ "}" }}
      {{ "}" }}
    </style>
{{ super() }}

<meta name="readthedocs-addons-api-version" content="1">
<script type="text/javascript">
 function onSwitch(event) {
     const option = event.target.selectedIndex;
     const item = event.target.options[option];
     window.location.href = item.dataset.url;
 }

 document.addEventListener("readthedocs-addons-data-ready", function(event) {
   const config = event.detail.data()

   // Add some mocked hardcoded versions pointing to the official
   // documentation while migrating to Read the Docs.
   // These are only for testing purposes.
   // TODO: remove them when managing all the versions on Read the Docs,
   // since all the "active, built and not hidden" versions will be shown automatically.
   let versions = config.versions.active.concat([
       {
           slug: "dev (3.13)",
           urls: {
               documentation: "https://docs.python.org/3.13/",
           }
       },
       {
           slug: "3.12",
           urls: {
               documentation: "https://docs.python.org/3.12/",
           }
       },
       {
           slug: "3.11",
           urls: {
               documentation: "https://docs.python.org/3.11/",
           }
       },
   ]);

   const versionSelect = `
   <select id="version_select">
   ${ versions.map(
       (version) => `
       <option
           value="${ version.slug }"
           ${ config.versions.current.slug === version.slug ? 'selected="selected"' : '' }
           data-url="${ version.urls.documentation }">
           ${ version.slug }
       </option>`
   ).join("\n") }
   </select>
   `;

   // Prepend the current language to the options on the selector
   let languages = config.projects.translations.concat(config.projects.current);
   languages = languages.sort((a, b) => a.language.name.localeCompare(b.language.name));

   const languageSelect = `
   <select id="language_select">
   ${ languages.map(
       (translation) => `
       <option
           value="${ translation.slug }"
           ${ config.projects.current.slug === translation.slug ? 'selected="selected"' : '' }
           data-url="${ translation.urls.documentation }">
           ${ translation.language.name }
       </option>`
   ).join("\n") }
   </select>
   `;

   // Query all the placeholders because there are different ones for Desktop/Mobile
   const versionPlaceholders = document.querySelectorAll(".version_switcher_placeholder");
   for (placeholder of versionPlaceholders) {
       placeholder.innerHTML = versionSelect;
       let selectElement = placeholder.querySelector("select");
       selectElement.addEventListener("change", onSwitch);
   }

   const languagePlaceholders = document.querySelectorAll(".language_switcher_placeholder");
   for (placeholder of languagePlaceholders) {
       placeholder.innerHTML = languageSelect;
       let selectElement = placeholder.querySelector("select");
       selectElement.addEventListener("change", onSwitch);
   }
 });
</script>
{% endblock %}
