1(function() {
2  'use strict';
3
4  // Parses versions in URL segments like:
5  // "3", "dev", "release/2.7" or "3.6rc2"
6  var version_regexs = [
7    '(?:\\d)',
8    '(?:\\d\\.\\d[\\w\\d\\.]*)',
9    '(?:dev)',
10    '(?:release/\\d.\\d[\\x\\d\\.]*)'];
11
12  var all_versions = {
13    '3.10': 'dev (3.10)',
14    '3.9': 'pre (3.9)',
15    '3.8': '3.8',
16    '3.7': '3.7',
17    '3.6': '3.6',
18    '2.7': '2.7',
19  };
20
21  var all_languages = {
22      'en': 'English',
23      'fr': 'French',
24      'ja': 'Japanese',
25      'ko': 'Korean',
26      'pt-br': 'Brazilian Portuguese',
27      'zh-cn': 'Simplified Chinese',
28  };
29
30  function build_version_select(current_version, current_release) {
31    var buf = ['<select>'];
32
33    $.each(all_versions, function(version, title) {
34      buf.push('<option value="' + version + '"');
35      if (version == current_version)
36        buf.push(' selected="selected">' + current_release + '</option>');
37      else
38        buf.push('>' + title + '</option>');
39    });
40
41    buf.push('</select>');
42    return buf.join('');
43  }
44
45  function build_language_select(current_language) {
46    var buf = ['<select>'];
47
48    $.each(all_languages, function(language, title) {
49      if (language == current_language)
50        buf.push('<option value="' + language + '" selected="selected">' +
51                 all_languages[current_language] + '</option>');
52      else
53        buf.push('<option value="' + language + '">' + title + '</option>');
54    });
55    if (!(current_language in all_languages)) {
56        // In case we're browsing a language that is not yet in all_languages.
57        buf.push('<option value="' + current_language + '" selected="selected">' +
58                 current_language + '</option>');
59        all_languages[current_language] = current_language;
60    }
61    buf.push('</select>');
62    return buf.join('');
63  }
64
65  function navigate_to_first_existing(urls) {
66    // Navigate to the first existing URL in urls.
67    var url = urls.shift();
68    if (urls.length == 0) {
69      window.location.href = url;
70      return;
71    }
72    $.ajax({
73      url: url,
74      success: function() {
75        window.location.href = url;
76      },
77      error: function() {
78        navigate_to_first_existing(urls);
79      }
80    });
81  }
82
83  function on_version_switch() {
84    var selected_version = $(this).children('option:selected').attr('value') + '/';
85    var url = window.location.href;
86    var current_language = language_segment_from_url(url);
87    var current_version = version_segment_in_url(url);
88    var new_url = url.replace('.org/' + current_language + current_version,
89                              '.org/' + current_language + selected_version);
90    if (new_url != url) {
91      navigate_to_first_existing([
92        new_url,
93        url.replace('.org/' + current_language + current_version,
94                    '.org/' + selected_version),
95        'https://docs.python.org/' + current_language + selected_version,
96        'https://docs.python.org/' + selected_version,
97        'https://docs.python.org/'
98      ]);
99    }
100  }
101
102  function on_language_switch() {
103    var selected_language = $(this).children('option:selected').attr('value') + '/';
104    var url = window.location.href;
105    var current_language = language_segment_from_url(url);
106    var current_version = version_segment_in_url(url);
107    if (selected_language == 'en/') // Special 'default' case for english.
108      selected_language = '';
109    var new_url = url.replace('.org/' + current_language + current_version,
110                              '.org/' + selected_language + current_version);
111    if (new_url != url) {
112      navigate_to_first_existing([
113        new_url,
114        'https://docs.python.org/'
115      ]);
116    }
117  }
118
119  // Returns the path segment of the language as a string, like 'fr/'
120  // or '' if not found.
121  function language_segment_from_url(url) {
122    var language_regexp = '\.org/([a-z]{2}(?:-[a-z]{2})?/)';
123    var match = url.match(language_regexp);
124    if (match !== null)
125        return match[1];
126    return '';
127  }
128
129  // Returns the path segment of the version as a string, like '3.6/'
130  // or '' if not found.
131  function version_segment_in_url(url) {
132    var language_segment = '(?:[a-z]{2}(?:-[a-z]{2})?/)';
133    var version_segment = '(?:(?:' + version_regexs.join('|') + ')/)';
134    var version_regexp = '\\.org/' + language_segment + '?(' + version_segment + ')';
135    var match = url.match(version_regexp);
136    if (match !== null)
137      return match[1];
138    return ''
139  }
140
141  $(document).ready(function() {
142    var release = DOCUMENTATION_OPTIONS.VERSION;
143    var language_segment = language_segment_from_url(window.location.href);
144    var current_language = language_segment.replace(/\/+$/g, '') || 'en';
145    var version = release.substr(0, 3);
146    var version_select = build_version_select(version, release);
147
148    $('.version_switcher_placeholder').html(version_select);
149    $('.version_switcher_placeholder select').bind('change', on_version_switch);
150
151    var language_select = build_language_select(current_language);
152
153    $('.language_switcher_placeholder').html(language_select);
154    $('.language_switcher_placeholder select').bind('change', on_language_switch);
155  });
156})();
157