Mercurial Hosting > freedit
view src/thread.html.luan @ 43:298c71e0c854
caching
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 09 Nov 2022 23:05:01 -0700 |
parents | 0c1b820fff34 |
children | 96f0c3d65698 |
line wrap: on
line source
local Luan = require "luan:Luan.luan" local error = Luan.error local ipairs = Luan.ipairs or error() local Time = require "luan:Time.luan" local time_now = Time.now or error() local Html = require "luan:Html.luan" local html_encode = Html.encode or error() local Io = require "luan:Io.luan" local Http = require "luan:http/Http.luan" local Shared = require "site:/lib/Shared.luan" local head = Shared.head or error() local header = Shared.header or error() local footer = Shared.footer or error() local delete_post = Shared.delete_post or error() local show_post = Shared.show_post or error() local Forum = require "site:/lib/Forum.luan" local forum_title = Forum.title or error() local Db = require "site:/lib/Db.luan" local Post = require "site:/lib/Post.luan" local Bbcode = require "site:/lib/Bbcode.luan" local bbcode_to_html = Bbcode.to_html or error() local User = require "site:/lib/User.luan" return function() local root_id = Http.request.parameters.root or error() local docs, total_hits = Db.search("post_root_id:"..root_id,1,1000,{sort="id"}) local posts = Post.from_docs(docs) local subject_html = posts[1].subject_html local user = User.current() local user_name = user and user.name local now = time_now() Io.stdout = Http.response.text_writer() %> <!doctype html> <html> <head> <% head() %> <title><%=forum_title%>: <%=subject_html%></title> <style> div[author] { margin-bottom: 6px; font-size: 10px; } div[author] img { width: 28px; vertical-align: middle; border-radius: 50%; } div[author] a { font-weight: bold; } span[ago] { color: #888; } [message] { white-space: pre-wrap; line-height: 1.4; } textarea { width: 100%; xmax-width: 450px; xheight: 100px; } <% if user_name == nil then %> [logged_in] { display: none; } <% end %> [only_user] { display: none; } <% if user_name ~= nil then %> [only_user="<%=html_encode(user_name)%>"] { display: initial; } <% end %> div[post]:first-of-type [delete_opton] { display: none; } body[thread_size="1"] div[post]:first-of-type [delete_opton] { display: initial; } </style> <script> function getPostDiv(node) { do { if( node.getAttribute('post') ) return node; } while( node = node.parentNode ); } function cancelEdit(src) { let postDiv = getPostDiv(src); postDiv.querySelector('[output]').style.display = 'block'; postDiv.querySelector('[edit]').innerHTML = ''; } function saveEdit(src) { let postDiv = getPostDiv(src); let post = postDiv.getAttribute('post'); let text = postDiv.querySelector('textarea').value; cancelEdit(src); let postData = 'post=' + post + '&text=' + encodeURIComponent(text); ajax('save_edit.js',postData); } function updated(postId,html) { let postDiv = document.querySelector('[post="'+postId+'"]'); if(postDiv) postDiv.querySelector('[message]').innerHTML = html; } function newPost() { let postDiv = document.querySelector('[post="new"]'); let textarea = postDiv.querySelector('textarea') let text = textarea.value; textarea.value = ''; let postData = 'root=<%=root_id%>&text=' + encodeURIComponent(text); ajax('new_post.js',postData); } function added(postId,html,thread_size) { if( document.querySelector('[post="'+postId+'"]') ) return; let newDiv = document.querySelector('[post="new"]'); newDiv.insertAdjacentHTML('beforebegin',html); document.body.setAttribute('thread_size',thread_size); } function uploaded(input,url,filename) { let postDiv = getPostDiv(input); let textarea = postDiv.querySelector('textarea'); textarea.focus(); textarea.setRangeText(url,textarea.selectionStart,textarea.selectionEnd,'select'); } function deletePost(span) { span.innerHTML = document.querySelector('[hidden][delete]').innerHTML; } function deleteNo(span) { span.innerHTML = document.querySelector('[hidden][undelete]').innerHTML; } function deleteYes(span) { let post = getPostDiv(span).getAttribute('post'); ajax( '/delete.js?post=' + post ); } function deleted(postId,thread_size) { let postDiv = document.querySelector('[post="'+postId+'"]'); if(!postDiv) return postDiv.outerHTML = ''; document.body.setAttribute('thread_size',thread_size); } function init() { let spans = document.querySelectorAll('span[ago]'); for( let i=0; i<spans.length; i++ ) { let span = spans[i]; let date = span.getAttribute('date'); date = parseInt(date); span.title = new Date(date).toLocaleString(); } } let eventSource = new EventSource(location.href); eventSource.onmessage = function(event) { eval( event.data ); }; </script> </head> <body onload="init()" thread_size="<%=Post.thread_size(root_id)%>"> <% header() %> <div content> <h1><%=subject_html%></h1> <% for _, post in ipairs(posts) do show_post(post,now) end %> <div post=new logged_in> <hr> <textarea oninput="fixTextarea(this)"></textarea> <p> <input type=file onchange="upload(this,uploaded)"> <button onclick="fileButtonClick(this)">Upload File</button> <button onclick="newPost()">save</button> </p> </div> </div> <% 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><%delete_post()%></span> <div hidden edit> <textarea oninput="fixTextarea(this)"></textarea> <p> <input type=file onchange="upload(this,uploaded)"> <button onclick="fileButtonClick(this)">Upload File</button> <button onclick="saveEdit(this)">save</button> <button onclick="cancelEdit(this)">cancel</button> </p> </div> </body> </html> <% end