Last active
February 7, 2024 19:29
-
-
Save bradgessler/dbf19c266e503489993582692beb36d3 to your computer and use it in GitHub Desktop.
Bi-directional HTML
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "bundler/inline" | |
gemfile do | |
source "https://rubygems.org" | |
gem "sinatra", "~> 3.1" | |
gem "nokogiri", "~> 1.15" | |
gem "puma" | |
end | |
require "sinatra" | |
get "/" do | |
erb :app | |
end | |
post "/" do | |
dom = Nokogiri::HTML(request.body.read) | |
todo_input = dom.at("#todo_input") | |
# Find the ul (or ol) that contains the li elements | |
list = dom.at_css('ul') # or dom.at_css('ol') if it's an ordered list | |
# Create a new li element with the content set to the current time | |
new_item = Nokogiri::XML::Node.new('li', dom) | |
if todo_input.content.empty? | |
todo_input.content = "This can't be empty dude!" | |
else | |
new_item.content = todo_input.content | |
todo_input.content = "" | |
# Append the new item to the list | |
list.prepend_child(new_item) | |
end | |
dom.to_html | |
end | |
get "/form" do | |
erb :form | |
end | |
post "/form" do | |
dom = Nokogiri::HTML(request.body.read) | |
dom.at_css("h1").content = "Updated at #{Time.now}" | |
dom.css("[contenteditable]").each do |element| | |
puts element.content | |
end | |
dom.to_html | |
end | |
Sinatra::Application.run! inline_templates: true | |
__END__ | |
@@form | |
<style> | |
.label { font-weight: bold; } | |
html { font-size: 125%; } | |
</style> | |
<h1>FORM</h1> | |
<div> | |
<div class="label">Name</div> | |
<div contenteditable>Your Name</div> | |
</div> | |
<div> | |
<div class="label">Email</div> | |
<div contenteditable>you@email.com</div> | |
</div> | |
<span class="button" href>Submit</span> | |
<span href="/">Home</span> | |
@@ app | |
<h1 id="todo_input" contenteditable autofocus></h1> | |
<div href>Add Item</div> | |
<ul reversed> | |
<li>First Item</li> | |
</ul> | |
@@ layout | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
<title>The App</title> | |
<style> | |
[href] { | |
user-select: none; | |
cursor: pointer; | |
text-decoration: underline; | |
color: blue; | |
} | |
[contenteditable] { | |
border: 1px dotted blue; | |
} | |
.button { | |
display: inline-block; | |
border-radius: 0.5rem; | |
padding: 0.25rem; | |
border: 1px solid #ccc; | |
background: #eee; | |
} | |
</style> | |
</head> | |
<body> | |
<%= yield %> | |
<script> | |
function setupEventListeners() { | |
document.body.addEventListener('click', function(event) { | |
if (event.target.matches('[href]')) { | |
event.preventDefault(); | |
const htmlContent = document.documentElement.outerHTML; | |
const postUrl = event.target.getAttribute('href') || document.location.href; | |
fetch(postUrl, { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'text/html' | |
}, | |
body: htmlContent | |
}) | |
.then(response => response.text()) | |
.then(newHtml => { | |
document.documentElement.innerHTML = newHtml; | |
setupEventListeners(); // Re-setup the event listeners after the new content is loaded | |
}) | |
.catch(error => console.error('Error:', error)); | |
} | |
}); | |
} | |
// Initialize event listeners on page load | |
setupEventListeners(); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment