diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index ad54ff16b..4d7b7378b 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -1,46 +1,140 @@ -function assign_href(a, url, path) { - fetch(url + "/" + path).then(response => { +/** +* Returns a promise for resolving a URL corresponding to a versioned resource (if one exists). +* +* @private +* @param {string} url - base URL +* @param {string} path - resource path +* @returns {Promise} promise which resolves a resource URL +*/ +function href(url, path) { + const defaultURL = url + "/index.html"; + url += "/" + path; + + // If a versioned resource exists, return the resource's URL; otherwise, return a default URL: + const opts = { + 'method': 'HEAD' + }; + return fetch(url, opts).then(onResponse).catch(onError); + + /** + * Callback invoked upon successfully resolving a resource. + * + * @private + * @param {Object} response - response object + */ + function onResponse(response) { if (response.ok) { - a.href = url + "/" + path; - } else { - a.href = url + "/index.html"; + return url; } - }).catch(error => { - a.href = url + "/index.html"; - }); + return defaultURL; + } + + /** + * Callback invoked upon failing to resolve a resource. + * + * @private + * @param {Error} error - error object + */ + function onError(error) { + return defaultURL; + } } -function add_version_dropdown(json_loc, target_loc, text) { - var dropdown = document.createElement("div"); +/** +* Adds a version dropdown menu with custom URL paths depending on the current page. +* +* @param {string} json_loc - JSON URL +* @param {string} target_loc - target URL +* @param {string} text - text +* @returns {Promise} promise which resolves upon adding a version menu +*/ +async function add_version_dropdown(json_loc, target_loc, text) { + const dropdown = document.createElement("div"); dropdown.className = "md-flex__cell md-flex__cell--shrink dropdown"; - var button = document.createElement("button"); + + const button = document.createElement("button"); button.className = "dropdownbutton"; - var content = document.createElement("div"); + + const content = document.createElement("div"); content.className = "dropdown-content md-hero"; + dropdown.appendChild(button); dropdown.appendChild(content); - $.getJSON(json_loc, function(versions) { - var currentURL = window.location.href; - var path = currentURL.split(/_site|array_api/)[1]; + + const opts = { + 'method': 'GET' + }; + await fetch(json_loc, opts).then(onResponse).then(onVersions).catch(onError); + + /** + * Callback invoked upon resolving a resource. + * + * @private + * @param {Object} response - response object + */ + function onResponse(response) { + return response.json(); + } + + /** + * Callback invoked upon resolving a JSON resource. + * + * @private + * @param {Object} versions - versions object + * @returns {Promise} promise which resolves upon processing version data + */ + async function onVersions(versions) { + // Resolve the current browser URL: + const currentURL = window.location.href; + + // Check whether the user is currently on a resource page (e.g., is viewing the specification for a particular function): + let path = currentURL.split(/_site|array\-api/)[1]; + + // Extract the resource subpath: if (path) { path = path.split("/"); path = path.slice(2, path.length); path = path.join("/"); - for (var key in versions) { - if (versions.hasOwnProperty(key)) { - var a = document.createElement("a"); - a.innerHTML = key; - a.title = key; - assign_href(a, target_loc + versions[key], path); - content.appendChild(a); - } + } else { + path = ""; + } + // For each version, create an anchor element and attempt to resolve a given resource for that version... + const promises = []; + const el = []; + for (let key in versions) { + if (versions.hasOwnProperty(key)) { + let a = document.createElement("a"); + a.innerHTML = key; + a.title = key; + el.push(a); + promises.push(href(target_loc + versions[key], path)); } } - }).done(function() { + // Resolve all resource URLs: + const urls = await Promise.all(promises); + + // Append the version links to the dropdown menu: + for (let i = 0; i < urls.length; i++) { + let a = el[i]; + a.href = urls[i]; + content.appendChild(a); + } + // Set the button text: button.innerHTML = text; - }).fail(function() { + + // Append dropdown: + $(".navheader").append(dropdown); + } + + /** + * Callback invoked upon failing to resolve a resource. + * + * @private + */ + function onError() { button.innerHTML = "Other Versions Not Found"; - }).always(function() { + + // Append dropdown: $(".navheader").append(dropdown); - }); + } };