index.html 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <html>
  2. <head>
  3. <title>Wobbly, the Web-based Gemini Browser</title>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width,initial-scale=1">
  6. <link rel='icon' href='data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>♊️</text></svg>'>
  7. <style>
  8. body { margin: 0; padding: 0 0 5em}
  9. #wobbly-toolbar { background-color: #cccccc; width: 100%; position: fixed; top: 0; }
  10. #wobbly-tools { display: flex; max-width: 60em; padding: 0.2em; margin: auto; }
  11. #wobbly-tools input { flex-basis: 100%; }
  12. #wobbly-help { display: none; background-color: #ffffcc; }
  13. #wobbly-help-text { max-width: 45em; margin: auto; padding: 1.5em 1em 0.5em; }
  14. #wobbly-window { max-width: 45em; margin: auto; padding: 2em 1em 5em; }
  15. </style>
  16. <script>
  17. var geminiHistory = []
  18. var geminiPresent = 0
  19. function geminiInit(){
  20. document.getElementById("wobbly-window").innerHTML = ""
  21. var startpage = "gemini://warmedal.se/~wobbly/"
  22. query_string = window.location.href.split('?')
  23. if (query_string.length > 1){
  24. startpage = query_string[1]
  25. }
  26. document.getElementById("wobbly-addressbar").value = startpage
  27. geminiHistory.push({url:startpage})
  28. geminiGo()
  29. }
  30. function geminiHelpToggle(){
  31. if (document.getElementById("wobbly-help-button").innerHTML === 'Help') {
  32. document.getElementById("wobbly-help").style.display = 'block'
  33. document.getElementById("wobbly-help-button").innerHTML = "Unhelp"
  34. } else {
  35. document.getElementById("wobbly-help").style.display = 'none'
  36. document.getElementById("wobbly-help-button").innerHTML = "Help"
  37. }
  38. }
  39. function geminiGo(){
  40. url = document.getElementById("wobbly-addressbar").value.trim().split("?")[0]
  41. if (url.length == 0) {
  42. return
  43. }
  44. if (! url.startsWith("gemini://")) {
  45. url = "gemini://" + url
  46. }
  47. if (! (url === geminiHistory[geminiPresent].url)) {
  48. geminiPresent++
  49. geminiHistory[geminiPresent] = {url:url}
  50. while (geminiHistory.length > geminiPresent +1) {
  51. geminiHistory.pop()
  52. }
  53. }
  54. var xmlHttp = new XMLHttpRequest()
  55. xmlHttp.open( "GET", "browser.cgi?" + url )
  56. xmlHttp.onload = function (e) {
  57. var body = xmlHttp.responseText
  58. document.getElementById("wobbly-window").innerHTML = body
  59. geminiHistory[geminiPresent].body = body
  60. }
  61. xmlHttp.send(null)
  62. }
  63. function geminiBack(){
  64. if (geminiPresent > 0) {
  65. geminiPresent--
  66. document.getElementById("wobbly-addressbar").value = geminiHistory[geminiPresent].url
  67. document.getElementById("wobbly-window").innerHTML = geminiHistory[geminiPresent].body
  68. }
  69. }
  70. // Big thanks to idiomdrottning for fixing my geminiUp function <3
  71. function geminiUp(){
  72. var components = geminiHistory[geminiPresent].url.match(/\/[^/]*/g)
  73. if ("/" == components.pop()) components.pop()
  74. if (components.length == 1) return
  75. document.getElementById("wobbly-addressbar").value = "gemini:" + components.join("") + "/"
  76. geminiGo()
  77. }
  78. function geminiForward(){
  79. if (geminiPresent < geminiHistory.length - 1) {
  80. geminiPresent++
  81. document.getElementById("wobbly-addressbar").value = geminiHistory[geminiPresent].url
  82. document.getElementById("wobbly-window").innerHTML = geminiHistory[geminiPresent].body
  83. }
  84. }
  85. function geminiEnterListener(e) {
  86. if(e.keyCode === 13) {
  87. e.preventDefault()
  88. geminiGo()
  89. }
  90. }
  91. function geminiLinkClickListener(e) {
  92. var e = window.e || e;
  93. if (e.target.tagName === 'A' && e.target.href.startsWith("gemini://")) {
  94. // We only care about clicked gemini:// links
  95. e.preventDefault()
  96. document.getElementById("wobbly-addressbar").value = e.target.href
  97. geminiGo()
  98. } else {
  99. return;
  100. }
  101. }
  102. if (document.addEventListener) {
  103. document.addEventListener('click', geminiLinkClickListener, false);
  104. } else {
  105. document.attachEvent('onclick', geminiLinkClickListener);
  106. }
  107. </script>
  108. </head>
  109. <body onload="geminiInit()">
  110. <div id="wobbly-toolbar">
  111. <div id="wobbly-tools">
  112. <button onclick="geminiHelpToggle()" id="wobbly-help-button">Help</button>
  113. <button onclick="geminiBack()" id="wobbly-back">⬅️</button>
  114. <button onclick="geminiUp()" id="wobbly-up">⬆️</button>
  115. <button onclick="geminiForward()" id="wobbly-forward">➡️</button>
  116. <input id="wobbly-addressbar" onkeypress="geminiEnterListener(event)"/>
  117. <button onclick="geminiGo()" id="wobbly-go">Go!</button>
  118. </div>
  119. </div>
  120. <div id="wobbly-help">
  121. <div id="wobbly-help-text">
  122. <h1>Wobbly Help Section</h1>
  123. <ul>
  124. <li>This browser is for casual reading. It only supports text documents, and only cares about any sort of layout in gemtext ones.</li>
  125. <li>Javascript has no notion of sockets that aren't http/https. Therefore all traffic from here goes through a web server that fetches and serves the gemini pages translated to html. Input and client certificates are not supported, because they would be unsafe under these circumstances.</li>
  126. <li>'Back' and 'Forward' buttons take you to cached versions of those pages. Pressing 'Go!' without typing in a new URL is a refresh.</li>
  127. <li>'Up' means to go one level higher in the path on the current domain. If you are on 'gemini://warmedal.se/~antenna/' and press 'Up' you will visit 'gemini://warmedal.se/'.</li>
  128. <li>Non-gemini links will open in a new tab in your browser as usual!</li>
  129. </ul>
  130. </div>
  131. </div>
  132. <div id="wobbly-window">
  133. <h1>This Browser Requires Javascript</h1>
  134. <p>Sorry, there's no meaningful way around that. It's not terribly much, however. Feel free to check the source code.</p>
  135. </div>
  136. </body>
  137. </html>