changeset 19:da006d1c1eba

use contentEditable
author Franklin Schmidt <fschmidt@gmail.com>
date Wed, 13 Jul 2022 08:47:13 -0600
parents 94e26bffd4fb
children 3ea49246d6a7
files .hgignore src/edit.js.luan src/save_edit.js.luan src/site.css src/test/editor.html src/thread.html.luan
diffstat 6 files changed, 79 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Jul 11 12:14:05 2022 -0600
+++ b/.hgignore	Wed Jul 13 08:47:13 2022 -0600
@@ -4,3 +4,4 @@
 local/
 *.bck
 push.sh
+.DS_Store
--- a/src/edit.js.luan	Mon Jul 11 12:14:05 2022 -0600
+++ b/src/edit.js.luan	Wed Jul 13 08:47:13 2022 -0600
@@ -5,30 +5,20 @@
 local Parsers = require "luan:Parsers.luan"
 local json_string = Parsers.json_string or error()
 local Io = require "luan:Io.luan"
-local output_of = Io.output_of or error()
 local Http = require "luan:http/Http.luan"
 local Post = require "site:/lib/Post.luan"
 
 
-local function form(post)
-%>
-					<p><textarea name=content><%=html_encode(post.content)%></textarea></p>
-					<p>
-						<a href="javascript:saveEdit('<%= post.id %>')">save</a>
-						<a href="javascript:cancelEdit('<%= post.id %>')">cancel</a>
-					</p>
-<%
-end
-
 return function()
 	local post = Http.request.parameters.post or error()
 	post = Post.get_by_id(post) or error()
-	local html = output_of(function() form(post) end)
 	Io.stdout = Http.response.text_writer()
 %>
 let postDiv = document.querySelector('[post="<%=post.id%>"]');
 postDiv.querySelector('[output]').style.display = 'none';
-postDiv.querySelector('[edit]').innerHTML = <%= json_string(html) %>;
-postDiv.querySelector('textarea').focus();
+postDiv.querySelector('[edit]').innerHTML = document.querySelector('[hidden][edit]').innerHTML;
+let contentEditable = postDiv.querySelector('[contentEditable]');
+contentEditable.innerHTML = <%= json_string(html_encode(post.content)) %>;
+contentEditable.focus();
 <%
 end
--- a/src/save_edit.js.luan	Mon Jul 11 12:14:05 2022 -0600
+++ b/src/save_edit.js.luan	Wed Jul 13 08:47:13 2022 -0600
@@ -25,8 +25,8 @@
 	local html = output_of(function() bbcode_to_html(post.content) end)
 	Io.stdout = Http.response.text_writer()
 %>
-cancelEdit('<%=post.id%>');
 let postDiv = document.querySelector('[post="<%=post.id%>"]');
+cancelEdit(postDiv);
 postDiv.querySelector('[message]').innerHTML = <%= json_string(html) %>;
 <%
 end
--- a/src/site.css	Mon Jul 11 12:14:05 2022 -0600
+++ b/src/site.css	Wed Jul 13 08:47:13 2022 -0600
@@ -20,6 +20,11 @@
 	xpadding: 7px;
 	xborder-color: #DDDDDD;
 }
+div[contenteditable] {
+	padding: 7px;
+	border: 1px solid #777;
+	white-space: pre-wrap;
+}
 
 div[header], div[footer] {
 	font-size: 14px;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/editor.html	Wed Jul 13 08:47:13 2022 -0600
@@ -0,0 +1,46 @@
+<!doctype html>
+<html>
+	<head>
+		<meta name="viewport" content="width=device-width, initial-scale=1">
+		<style>
+			[contentEditable] {
+				padding: 7px;
+				border: 1px solid #777;
+				white-space: pre-wrap;
+			}
+		</style>
+		<script>
+			function log() {
+				let edit = document.querySelector('[contentEditable]');
+				console.log(edit.innerHTML);
+				//console.log(edit.textContent);
+			}
+			function test() {
+				let edit = document.querySelector('[contentEditable]');
+				edit.focus();
+				let s = getSelection();
+				let r = s.getRangeAt(0);
+				//console.log(s);
+				r.deleteContents();
+				let t = document.createTextNode('\n');
+				r.insertNode(t);
+				r.collapse();
+			}
+		</script>
+	</head>
+	<body>
+		<p>top</p>
+		<div contentEditable>
+aaa <b>bbb</b> <i>iii</i>
+1
+2
+3
+zzz
+		</div>
+		<p>
+			<button onclick="log()">log</button>
+			<button onclick="test()">test</button>
+		</p>
+		<p>bottom</p>
+	</body>
+</html>
--- a/src/thread.html.luan	Mon Jul 11 12:14:05 2022 -0600
+++ b/src/thread.html.luan	Wed Jul 13 08:47:13 2022 -0600
@@ -56,21 +56,24 @@
 			[message] {
 				white-space: pre-wrap;
 			}
-			textarea {
-				width: 100%;
-				max-width: 450px;
-				height: 100px;
-			}
 		</style>
 		<script>
-			function cancelEdit(post) {
-				let postDiv = document.querySelector('[post="'+post+'"]');
+			function getPostDiv(node) {
+				do {
+					if( node.getAttribute('post') )
+						return node;
+				} while( node = node.parentNode );
+			}
+
+			function cancelEdit(a) {
+				let postDiv = getPostDiv(a);
 				postDiv.querySelector('[output]').style.display = 'block';
 				postDiv.querySelector('[edit]').innerHTML = '';
 			}
-			function saveEdit(post) {
-				let postDiv = document.querySelector('[post="'+post+'"]');
-				let text = postDiv.querySelector('textarea').value;
+			function saveEdit(a) {
+				let postDiv = getPostDiv(a);
+				let post = postDiv.getAttribute('post');
+				let text = postDiv.querySelector('[contentEditable]').textContent;
 				let postData = 'post=' + post + '&text=' + encodeURIComponent(text);
 				ajax("save_edit.js",postData);
 			}
@@ -82,7 +85,7 @@
 				span.innerHTML = document.querySelector('[hidden][undelete]').innerHTML;
 			}
 			function deleteYes(span) {
-				let post = span.getAttribute('delete');
+				let post = getPostDiv(span).getAttribute('post');
 				ajax( '/delete.js?post=' + post );
 			}
 
@@ -119,7 +122,7 @@
 						<a href="/reply.html?parent=<%=post.id%>">reply</a>
 <%	if post.author_name == user_name then %>
 						- <a href="javascript:ajax('/edit.js?post=<%=post.id%>')">edit</a>
-						- <span delete="<%=post.id%>"><%deletePost()%></span>
+						- <span delete><%deletePost()%></span>
 <%	end %>
 					</p>
 				</div>
@@ -130,6 +133,13 @@
 <%		footer() %>
 		<span hidden delete>Delete? <a href="javascript:" onclick="deleteYes(parentNode)">yes</a> / <a href="javascript:" onclick="deleteNo(parentNode)">no</a></span>
 		<span hidden undelete><%deletePost()%></span>
+		<div hidden edit>
+			<div contentEditable></div>
+			<p>
+				<button onclick="saveEdit(this)">save</button>
+				<button onclick="cancelEdit(this)">cancel</button>
+			</p>
+		</div>
 	</body>
 </html>
 <%