1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
| const html = todos => ` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>Todos</title> <link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet"></link> </head> <body class="bg-blue-100"> <div class="w-full h-full flex content-center justify-center mt-8"> <div class="bg-white shadow-md rounded px-8 pt-6 py-8 mb-4"> <h1 class="block text-grey-800 text-md font-bold mb-2">Todos</h1> <div class="flex"> <input class="shadow appearance-none border rounded w-full py-2 px-3 text-grey-800 leading-tight focus:outline-none focus:shadow-outline" type="text" name="name" placeholder="A new todo"></input> <button class="bg-blue-500 hover:bg-blue-800 text-white font-bold ml-2 py-2 px-4 rounded focus:outline-none focus:shadow-outline" id="create" type="submit">Create</button> </div> <div class="mt-4" id="todos"></div> </div> </div> </body> <script> window.todos = ${todos} var updateTodos = function() { fetch("/", { method: 'PUT', body: JSON.stringify({ todos: window.todos }) }) populateTodos() } var completeTodo = function(evt) { var checkbox = evt.target var todoElement = checkbox.parentNode var newTodoSet = [].concat(window.todos) var todo = newTodoSet.find(t => t.id == todoElement.dataset.todo) todo.completed = !todo.completed window.todos = newTodoSet updateTodos() } var populateTodos = function() { var todoContainer = document.querySelector("#todos") todoContainer.innerHTML = null window.todos.forEach(todo => { var el = document.createElement("div") el.className = "border-t py-4" el.dataset.todo = todo.id var name = document.createElement("span") name.className = todo.completed ? "line-through" : "" name.textContent = todo.name var checkbox = document.createElement("input") checkbox.className = "mx-4" checkbox.type = "checkbox" checkbox.checked = todo.completed ? 1 : 0 checkbox.addEventListener('click', completeTodo) el.appendChild(checkbox) el.appendChild(name) todoContainer.appendChild(el) }) } populateTodos() var createTodo = function() { var input = document.querySelector("input[name=name]") if (input.value.length) { window.todos = [].concat(todos, { id: window.todos.length + 1, name: input.value, completed: false }) input.value = "" updateTodos() } } document.querySelector("#create").addEventListener('click', createTodo) </script> </html> `
const defaultData = { todos: [] }
const setCache = (key, data) => TODOS.put(key, data) const getCache = key => TODOS.get(key)
async function getTodos(request) { const ip = request.headers.get('CF-Connecting-IP') const cacheKey = `data-${ip}` let data const cache = await getCache(cacheKey) if (!cache) { await setCache(cacheKey, JSON.stringify(defaultData)) data = defaultData } else { data = JSON.parse(cache) } const body = html(JSON.stringify(data.todos || []).replace(/</g, "\ ")) return new Response(body, { headers: { 'Content-Type': 'text/html' }, }) }
async function updateTodos(request) { const body = await request.text() const ip = request.headers.get('CF-Connecting-IP') const cacheKey = `data-${ip}` try { JSON.parse(body) await setCache(cacheKey, body) return new Response(body, { status: 200 }) } catch (err) { return new Response(err, { status: 500 }) } }
async function handleRequest(request) { if (request.method === 'PUT') { return updateTodos(request) } else { return getTodos(request) } }
addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) })
|