From 5c124b81711ac51ff45963b5c698308e48d8f475 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 16:03:34 -0700 Subject: [PATCH 01/18] Refactor to use async/await and update URL manipulation logic --- spec/_static/javascripts/version_dropdown.js | 122 +++++++++++++++---- 1 file changed, 95 insertions(+), 27 deletions(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index ad54ff16b..0b12c8005 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -1,46 +1,114 @@ -function assign_href(a, url, path) { - fetch(url + "/" + path).then(response => { +/** +* Returns 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 +*/ +async function href(url, path) { + const defaultURL = url + "/index.html"; + url += "/" + path; + await fetch(url).then(onResponse).catch(onError); + + /** + * Success handler. + * + * @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; + } + + /** + * Error handler. + * + * @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]; + + await $.getJSON(json_loc, onVersions).done(onDone).fail(onFail).always(onAlways); + + /** + * Callback invoked upon successfully resolving a list of versions. + * + * @private + * @param {Object} versions - versions object + */ + async function onVersions(versions) { + const currentURL = window.location.href; + let path = currentURL.split(/_site|array_api/)[1]; 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 (let key in versions) { + if (versions.hasOwnProperty(key)) { + let a = document.createElement("a"); + a.innerHTML = key; + a.title = key; + a.href = await href(target_loc + versions[key], path); + content.appendChild(a); } } - }).done(function() { + } + + /** + * Callback invoked upon resolving a JSON resource. + * + * @private + */ + function onDone() { button.innerHTML = text; - }).fail(function() { + } + + /** + * Callback invoked upon failing to resolve a JSON resource. + * + * @private + */ + function onFail() { button.innerHTML = "Other Versions Not Found"; - }).always(function() { + } + + /** + * Callback which is always invoked upon attempting to resolve a JSON resource. + * + * @private + */ + function onAlways() { $(".navheader").append(dropdown); - }); + } }; From e21b169eed58e70b2bc58f2acf6ddbc9044e9f72 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 16:29:49 -0700 Subject: [PATCH 02/18] Remove duplicate success callback --- spec/_static/javascripts/version_dropdown.js | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index 0b12c8005..8a4371f97 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -56,15 +56,15 @@ async function add_version_dropdown(json_loc, target_loc, text) { dropdown.appendChild(button); dropdown.appendChild(content); - await $.getJSON(json_loc, onVersions).done(onDone).fail(onFail).always(onAlways); + await $.getJSON(json_loc).done(onDone).fail(onFail).always(onAlways); /** - * Callback invoked upon successfully resolving a list of versions. + * Callback invoked upon resolving a JSON resource. * * @private * @param {Object} versions - versions object */ - async function onVersions(versions) { + async function onDone(versions) { const currentURL = window.location.href; let path = currentURL.split(/_site|array_api/)[1]; if (path) { @@ -83,14 +83,6 @@ async function add_version_dropdown(json_loc, target_loc, text) { content.appendChild(a); } } - } - - /** - * Callback invoked upon resolving a JSON resource. - * - * @private - */ - function onDone() { button.innerHTML = text; } From 39d16db3a6ebc1cb595391d42d4d7558b26dbc46 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 16:33:51 -0700 Subject: [PATCH 03/18] Add comment --- spec/_static/javascripts/version_dropdown.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index 8a4371f97..d126a6859 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -9,6 +9,8 @@ async 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: await fetch(url).then(onResponse).catch(onError); /** From e4db25e4da0fcf358c821e845a3b5a9da6eb4909 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 16:34:36 -0700 Subject: [PATCH 04/18] Update function descriptions --- spec/_static/javascripts/version_dropdown.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index d126a6859..c66d51c65 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -14,7 +14,7 @@ async function href(url, path) { await fetch(url).then(onResponse).catch(onError); /** - * Success handler. + * Callback invoked upon successfully resolving a resource. * * @private * @param {Object} response - response object @@ -27,7 +27,7 @@ async function href(url, path) { } /** - * Error handler. + * Callback invoked upon failing to resolve a resource. * * @private * @param {Error} error - error object From 52aa78da1106c294d6e3ee8de4eed98460467e93 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 16:35:42 -0700 Subject: [PATCH 05/18] Update function docs --- spec/_static/javascripts/version_dropdown.js | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index c66d51c65..1772a561d 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -65,6 +65,7 @@ async function add_version_dropdown(json_loc, target_loc, text) { * * @private * @param {Object} versions - versions object + * @returns {Promise} promise which resolves upon processing version data */ async function onDone(versions) { const currentURL = window.location.href; From 6649c2013a31f8cbc6c80e5968a1f218b8de874d Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 16:40:11 -0700 Subject: [PATCH 06/18] Add debug statement --- spec/_static/javascripts/version_dropdown.js | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index 1772a561d..645879283 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -68,6 +68,7 @@ async function add_version_dropdown(json_loc, target_loc, text) { * @returns {Promise} promise which resolves upon processing version data */ async function onDone(versions) { + console.log(versions) const currentURL = window.location.href; let path = currentURL.split(/_site|array_api/)[1]; if (path) { From 3b32fe216021ab85f32ee9a54f102f9794d78d74 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 16:54:50 -0700 Subject: [PATCH 07/18] Add comments --- spec/_static/javascripts/version_dropdown.js | 29 ++++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index 645879283..a3d81751b 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -6,12 +6,12 @@ * @param {string} path - resource path * @returns {Promise} promise which resolves a resource URL */ -async function href(url, path) { +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: - await fetch(url).then(onResponse).catch(onError); + return fetch(url).then(onResponse).catch(onError); /** * Callback invoked upon successfully resolving a resource. @@ -68,9 +68,15 @@ async function add_version_dropdown(json_loc, target_loc, text) { * @returns {Promise} promise which resolves upon processing version data */ async function onDone(versions) { - console.log(versions) + console.log(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); @@ -78,15 +84,28 @@ async function add_version_dropdown(json_loc, target_loc, text) { } 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; - a.href = await href(target_loc + versions[key], path); - content.appendChild(a); + el.push(a); + promises.push(href(target_loc + versions[key], path)); } } + // 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; } From 74a2b1ac1a990d8390f04a7a212e77e4e5238bcf Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 16:55:55 -0700 Subject: [PATCH 08/18] Fix function description --- spec/_static/javascripts/version_dropdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index a3d81751b..6145549fc 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -1,5 +1,5 @@ /** -* Returns a URL corresponding to a versioned resource (if one exists). +* Returns a promise for resolving a URL corresponding to a versioned resource (if one exists). * * @private * @param {string} url - base URL From a8a3e51302b5243a85ce6c38b3b19269156c336d Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 17:08:01 -0700 Subject: [PATCH 09/18] Add debug statements --- spec/_static/javascripts/version_dropdown.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index 6145549fc..547df387a 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -58,7 +58,11 @@ async function add_version_dropdown(json_loc, target_loc, text) { dropdown.appendChild(button); dropdown.appendChild(content); - await $.getJSON(json_loc).done(onDone).fail(onFail).always(onAlways); + const p = $.getJSON(json_loc); + console.log(p); + + p.done(onDone).fail(onFail).always(onAlways); + await p; /** * Callback invoked upon resolving a JSON resource. @@ -115,6 +119,7 @@ async function add_version_dropdown(json_loc, target_loc, text) { * @private */ function onFail() { + console.log("Failure"); button.innerHTML = "Other Versions Not Found"; } @@ -124,6 +129,7 @@ async function add_version_dropdown(json_loc, target_loc, text) { * @private */ function onAlways() { + console.log("Always"); $(".navheader").append(dropdown); } }; From 02e31b4e3da96b6e83b485db54d170960dd7a809 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 17:15:58 -0700 Subject: [PATCH 10/18] Replace `done` with `then` --- spec/_static/javascripts/version_dropdown.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index 547df387a..cf290d24a 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -60,8 +60,8 @@ async function add_version_dropdown(json_loc, target_loc, text) { const p = $.getJSON(json_loc); console.log(p); - - p.done(onDone).fail(onFail).always(onAlways); + + p.then(onVersions).fail(onFail).always(onAlways); await p; /** @@ -71,7 +71,7 @@ async function add_version_dropdown(json_loc, target_loc, text) { * @param {Object} versions - versions object * @returns {Promise} promise which resolves upon processing version data */ - async function onDone(versions) { + async function onVersions(versions) { console.log(versions); // Resolve the current browser URL: From 05435222a7cc584c8682bf0df7b4abc3c081eb3a Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 17:24:23 -0700 Subject: [PATCH 11/18] Rearrange callback assignments --- spec/_static/javascripts/version_dropdown.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index cf290d24a..8f1e170cc 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -61,8 +61,9 @@ async function add_version_dropdown(json_loc, target_loc, text) { const p = $.getJSON(json_loc); console.log(p); - p.then(onVersions).fail(onFail).always(onAlways); - await p; + p.fail(onFail).always(onAlways); + + await p.then(onVersions); /** * Callback invoked upon resolving a JSON resource. @@ -119,7 +120,6 @@ async function add_version_dropdown(json_loc, target_loc, text) { * @private */ function onFail() { - console.log("Failure"); button.innerHTML = "Other Versions Not Found"; } From 281d236fc2a0dad068dc99bd9e271b0930ec164a Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 17:34:40 -0700 Subject: [PATCH 12/18] Invoke `promise` method to return a deferred object's promise --- spec/_static/javascripts/version_dropdown.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index 8f1e170cc..d5f85d1e5 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -61,9 +61,10 @@ async function add_version_dropdown(json_loc, target_loc, text) { const p = $.getJSON(json_loc); console.log(p); + p.then(onVersions); p.fail(onFail).always(onAlways); - await p.then(onVersions); + await p.promise(); /** * Callback invoked upon resolving a JSON resource. From 3350625bdcc27873da733067130bc9732bc9cb10 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 17:49:22 -0700 Subject: [PATCH 13/18] Refactor to use `fetch` --- spec/_static/javascripts/version_dropdown.js | 33 +++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index d5f85d1e5..d6083b018 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -58,13 +58,20 @@ async function add_version_dropdown(json_loc, target_loc, text) { dropdown.appendChild(button); dropdown.appendChild(content); - const p = $.getJSON(json_loc); - console.log(p); + const opts = { + 'method': 'GET' + }; + await fetch(json_loc, opts).then(onResponse).then(onVersions).catch(onError); - p.then(onVersions); - p.fail(onFail).always(onAlways); - - await p.promise(); + /** + * 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. @@ -113,24 +120,20 @@ async function add_version_dropdown(json_loc, target_loc, text) { } // Set the button text: button.innerHTML = text; + + // Append dropdown: + $(".navheader").append(dropdown); } /** - * Callback invoked upon failing to resolve a JSON resource. + * Callback invoked upon failing to resolve a resource. * * @private */ function onFail() { button.innerHTML = "Other Versions Not Found"; - } - /** - * Callback which is always invoked upon attempting to resolve a JSON resource. - * - * @private - */ - function onAlways() { - console.log("Always"); + // Append dropdown: $(".navheader").append(dropdown); } }; From 1c32d2e363a573322b441a969018872ef96ba2f1 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 17:50:06 -0700 Subject: [PATCH 14/18] Fix function name --- spec/_static/javascripts/version_dropdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index d6083b018..4b0e79501 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -130,7 +130,7 @@ async function add_version_dropdown(json_loc, target_loc, text) { * * @private */ - function onFail() { + function onError() { button.innerHTML = "Other Versions Not Found"; // Append dropdown: From 6c3068f77cc304bc84cd384ea6bdca8251e122ff Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 19:34:03 -0700 Subject: [PATCH 15/18] Fix regular expression --- spec/_static/javascripts/version_dropdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index 4b0e79501..f9e5b2cfd 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -87,7 +87,7 @@ async function add_version_dropdown(json_loc, target_loc, text) { 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]; + let path = currentURL.split(/_site|array\-api/)[1]; // Extract the resource subpath: if (path) { From 48d926f3017d9614e4458e7e94d64d00c4c08ca8 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 19:37:17 -0700 Subject: [PATCH 16/18] Add debug statements --- spec/_static/javascripts/version_dropdown.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index f9e5b2cfd..a462ec93f 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -9,7 +9,7 @@ function href(url, path) { const defaultURL = url + "/index.html"; url += "/" + path; - +console.log(url); // If a versioned resource exists, return the resource's URL; otherwise, return a default URL: return fetch(url).then(onResponse).catch(onError); @@ -81,14 +81,12 @@ async function add_version_dropdown(json_loc, target_loc, text) { * @returns {Promise} promise which resolves upon processing version data */ async function onVersions(versions) { - console.log(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]; - +console.log(path); // Extract the resource subpath: if (path) { path = path.split("/"); From 01e433ae653cff2da80518ee138beca274025112 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 19:45:49 -0700 Subject: [PATCH 17/18] Remove debug statements --- spec/_static/javascripts/version_dropdown.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index a462ec93f..a7a859f6b 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -9,7 +9,7 @@ function href(url, path) { const defaultURL = url + "/index.html"; url += "/" + path; -console.log(url); + // If a versioned resource exists, return the resource's URL; otherwise, return a default URL: return fetch(url).then(onResponse).catch(onError); @@ -86,7 +86,7 @@ async function add_version_dropdown(json_loc, target_loc, text) { // 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]; -console.log(path); + // Extract the resource subpath: if (path) { path = path.split("/"); From 4448b37741058d2c4c01e4056e775abdb7ab1637 Mon Sep 17 00:00:00 2001 From: Athan Reines Date: Sat, 8 Jul 2023 19:51:57 -0700 Subject: [PATCH 18/18] Perform head request rather than request entire resource --- spec/_static/javascripts/version_dropdown.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/_static/javascripts/version_dropdown.js b/spec/_static/javascripts/version_dropdown.js index a7a859f6b..4d7b7378b 100644 --- a/spec/_static/javascripts/version_dropdown.js +++ b/spec/_static/javascripts/version_dropdown.js @@ -11,7 +11,10 @@ function href(url, path) { url += "/" + path; // If a versioned resource exists, return the resource's URL; otherwise, return a default URL: - return fetch(url).then(onResponse).catch(onError); + const opts = { + 'method': 'HEAD' + }; + return fetch(url, opts).then(onResponse).catch(onError); /** * Callback invoked upon successfully resolving a resource.