interact-update.html 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. {% if site.use_jupyterhub_button or site.use_binder_button %}
  2. <script>
  3. /**
  4. * To auto-embed hub URLs in interact links if given in a RESTful fashion
  5. */
  6. function getJsonFromUrl(url) {
  7. var query = url.split('?');
  8. if (query.length < 2) {
  9. // No queries so just return false
  10. return false;
  11. }
  12. query = query[1];
  13. // Collect REST params into a dictionary
  14. var result = {};
  15. query.split("&").forEach(function(part) {
  16. var item = part.split("=");
  17. result[item[0]] = decodeURIComponent(item[1]);
  18. });
  19. return result;
  20. }
  21. function dict2param(dict) {
  22. params = Object.keys(dict).map(function(k) {
  23. return encodeURIComponent(k) + '=' + encodeURIComponent(dict[k])
  24. });
  25. return params.join('&')
  26. }
  27. // Parse a Binder URL, converting it to the string needed for JupyterHub
  28. function binder2Jupyterhub(url) {
  29. newUrl = {};
  30. parts = url.split('v2/gh/')[1];
  31. // Grab the base repo information
  32. repoinfo = parts.split('?')[0];
  33. var [org, repo, ref] = repoinfo.split('/');
  34. newUrl['repo'] = ['https://github.com', org, repo].join('/');
  35. newUrl['branch'] = ref
  36. // Grab extra parameters passed
  37. params = getJsonFromUrl(url);
  38. if (params['filepath'] !== undefined) {
  39. newUrl['subPath'] = params['filepath']
  40. }
  41. return dict2param(newUrl);
  42. }
  43. // Filter out potentially unsafe characters to prevent xss
  44. function safeUrl(url)
  45. {
  46. return String(encodeURIComponent(url))
  47. .replace(/&/g, '&amp;')
  48. .replace(/"/g, '&quot;')
  49. .replace(/'/g, '&#39;')
  50. .replace(/</g, '&lt;')
  51. .replace(/>/g, '&gt;');
  52. }
  53. function addParamToInternalLinks(hub) {
  54. var links = document.querySelectorAll("a").forEach(function(link) {
  55. var href = link.href;
  56. // If the link is an internal link...
  57. if (href.search("{{ site.url }}") !== -1 || href.startsWith('/') || href.search("127.0.0.1:") !== -1) {
  58. // Assume we're an internal link, add the hub param to it
  59. var params = getJsonFromUrl(href);
  60. if (params !== false) {
  61. // We have REST params, so append a new one
  62. params['jupyterhub'] = hub;
  63. } else {
  64. // Create the REST params
  65. params = {'jupyterhub': hub};
  66. }
  67. // Update the link
  68. var newHref = href.split('?')[0] + '?' + dict2param(params);
  69. link.setAttribute('href', decodeURIComponent(newHref));
  70. }
  71. });
  72. return false;
  73. }
  74. // Update interact links
  75. function updateInteractLink() {
  76. // hack to make this work since it expects a ? in the URL
  77. rest = getJsonFromUrl("?" + location.search.substr(1));
  78. jupyterHubUrl = rest['jupyterhub'];
  79. var hubType = null;
  80. var hubUrl = null;
  81. if (jupyterHubUrl !== undefined) {
  82. hubType = 'jupyterhub';
  83. hubUrl = jupyterHubUrl;
  84. }
  85. if (hubType !== null) {
  86. // Sanitize the hubUrl
  87. hubUrl = safeUrl(hubUrl);
  88. // Add HTTP text if omitted
  89. if (hubUrl.indexOf('http') < 0) {hubUrl = 'http://' + hubUrl;}
  90. var interactButtons = document.querySelectorAll("button.interact-button")
  91. var lastButton = interactButtons[interactButtons.length-1];
  92. var link = lastButton.parentElement;
  93. // If we've already run this, skip the link updating
  94. if (link.nextElementSibling !== null) {
  95. return;
  96. }
  97. // Update the link and add context div
  98. var href = link.getAttribute('href');
  99. if (lastButton.id === 'interact-button-binder') {
  100. // If binder links exist, we need to re-work them for jupyterhub
  101. if (hubUrl.indexOf('http%3A%2F%2Flocalhost') > -1) {
  102. // If localhost, assume we're working from a local Jupyter server and remove `/hub`
  103. first = [hubUrl, 'git-sync'].join('/')
  104. } else {
  105. first = [hubUrl, 'hub', 'user-redirect', 'git-sync'].join('/')
  106. }
  107. href = first + '?' + binder2Jupyterhub(href);
  108. } else {
  109. // If interact button isn't binderhub, assume it's jupyterhub
  110. // If JupyterHub links, we only need to replace the hub url
  111. href = href.replace("{{ site.jupyterhub_url }}", hubUrl);
  112. if (hubUrl.indexOf('http%3A%2F%2Flocalhost') > -1) {
  113. // Assume we're working from a local Jupyter server and remove `/hub`
  114. href = href.replace("/hub/user-redirect", "");
  115. }
  116. }
  117. link.setAttribute('href', decodeURIComponent(href));
  118. // Add text after interact link saying where we're launching
  119. hubUrlNoHttp = decodeURIComponent(hubUrl).replace('http://', '').replace('https://', '');
  120. link.insertAdjacentHTML('afterend', '<div class="interact-context">on ' + hubUrlNoHttp + '</div>');
  121. // Update internal links so we retain the hub url
  122. addParamToInternalLinks(hubUrl);
  123. }
  124. }
  125. runWhenDOMLoaded(updateInteractLink)
  126. document.addEventListener('turbolinks:load', updateInteractLink)
  127. </script>
  128. {% endif %}