From 1f04b83be337cc91a3fabcf4e574e2306f3d2eaa Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Sat, 30 Mar 2024 12:14:42 -0400 Subject: refactor --- web/public/css/common.css | 57 +++++++++++++++++++++++++++++++++++++ web/public/js/lib.js | 66 ++++++++++++++++++++++++++++++++++++++++++- web/public/js/modal.js | 64 ----------------------------------------- web/public/js/post.js | 38 ------------------------- web/public/js/routes/home.js | 0 web/public/js/shared/modal.js | 64 +++++++++++++++++++++++++++++++++++++++++ web/public/js/shared/post.js | 38 +++++++++++++++++++++++++ 7 files changed, 224 insertions(+), 103 deletions(-) delete mode 100644 web/public/js/modal.js delete mode 100644 web/public/js/post.js create mode 100644 web/public/js/routes/home.js create mode 100644 web/public/js/shared/modal.js create mode 100644 web/public/js/shared/post.js (limited to 'web/public') diff --git a/web/public/css/common.css b/web/public/css/common.css index 05f429f..84aabfc 100644 --- a/web/public/css/common.css +++ b/web/public/css/common.css @@ -52,6 +52,8 @@ body { } header { + top: 0; + position: sticky; height: 3.5rem; background-color: var(--primary); display: flex; @@ -145,6 +147,10 @@ input:focus { align-items: center; } +.nav { + position: sticky; +} + .nav-right { flex: 1; justify-content: flex-end; @@ -333,6 +339,30 @@ input:focus { border-radius: .5rem; display: flex; flex-direction: column; + animation: fadeIn .1s, slideInModal .1s linear; +} + +@keyframes slideInModal { + 0% { + animation-timing-function: ease-in; + transform: translate(-50%, -60%); + } +} + +@keyframes slideIn { + 0% { + animation-timing-function: ease-out; + transform: translate(0, -50%); + } +} + +@keyframes fadeIn { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } } .modal>form { @@ -402,3 +432,30 @@ button[type="submit"]:hover { background-color: var(--logo); } +#toast-container { + position: fixed; + top: 4rem; + left: 100%; + transform: translateX(-110%); + margin-top: 1rem; + z-index: 10000; +} + +.toast { + padding: .75rem; + margin: .5rem; + border-radius: .5rem; + min-width: 15rem; + font-family: sfpro; + animation: fadeIn .1s, slideIn .25s linear; + display: flex; + justify-content: space-between; +} + +.toast.error { + background-color: var(--error); +} + +.toast.success { + background-color: var(--success); +} diff --git a/web/public/js/lib.js b/web/public/js/lib.js index d822b02..7647208 100644 --- a/web/public/js/lib.js +++ b/web/public/js/lib.js @@ -1,4 +1,8 @@ +/// +/// document ready functions +/// + let ready = false; $(function() { @@ -15,9 +19,14 @@ var r$ = function(callback) { } } +/// +/// dom observer +/// checks for elements on the DOM now and added later +/// + function observe(containerSelector, elementSelector, callback) { - r$(() => { + r$(() => { $(containerSelector + ' ' + elementSelector).each(function (_, e) { let me = $(e); callback(me); @@ -37,9 +46,64 @@ function observe(containerSelector, elementSelector, callback) { }; var target = $(containerSelector)[0]; + + if (!target) { + console.warn('[observe] didnt find container: ', containerSelector); + return; + } + var config = { childList: true, subtree: true }; var MutationObserver = window.MutationObserver; var observer = new MutationObserver(onMutationsObserved); observer.observe(target, config); }); } + +/// +/// ajax setup +/// + +let ajaxHeaders = {}; +ajaxHeaders['Content-Type'] = 'application/json'; +if (jwtStr) { + ajaxHeaders['Authorization'] = 'Bearer ' + jwtStr +} + +$.ajaxSetup({ + headers: ajaxHeaders +}) + +/// +/// ajax error handle +/// + +var errorToast = (xhr) => { + let data = xhr.responseJSON; + let msg = data.message; + let detail = data.details; + let hint = data.hint; + + let query = '?msg=' + msg; + if (detail) { + query += '&detail=' + detail; + } + if (hint) { + query += '&hint=' + hint; + } + let url = '/template/toast' + query; + $.get(url, function (data) { + $('#toast-container').prepend(data); + }) +} + +observe('#toast-container', '.action-close-toast', function(el) { + el.on('click', function() { + el.parent().remove(); + }); + + setTimeout(function() { + el.parent().remove(); + }, 5000); +}); + + diff --git a/web/public/js/modal.js b/web/public/js/modal.js deleted file mode 100644 index 792cd85..0000000 --- a/web/public/js/modal.js +++ /dev/null @@ -1,64 +0,0 @@ -$(document).on('click', ".modal-close", (o) => { - $(o.target).closest('.modal-container').remove(); -}); - -const initDrag = (header, modal, container) => { - let drag = false; - - let mouseX, mouseY, modalX, modalY; - - const onStart = (e) => { - e = e || window.event; - e.preventDefault(); - mouseX = e.clientX; - mouseY = e.clientY; - drag = true; - }; - - const onDrag = (e) => { - e = e || window.event; - e.preventDefault(); - if (!drag) { - return; - } - modalX = mouseX - e.clientX; - modalY = mouseY - e.clientY; - mouseX = e.clientX; - mouseY = e.clientY; - - let posX = (modal.offsetLeft - modalX), - posY = (modal.offsetTop - modalY); - - let minX = modal.offsetWidth / 2, - minY = modal.offsetHeight / 2; - - let maxX = container.offsetWidth - minX, - maxY = container.offsetHeight - minY; - - posX = Math.max(minX, Math.min(maxX, posX)); - posY = Math.max(minY, Math.min(maxY, posY)); - - posX = posX / container.offsetWidth * 100; - posY = posY / container.offsetHeight * 100; - - modal.style.left = posX + "%"; - modal.style.top = posY + "%"; - }; - - const onEnd = () => { - drag = false; - }; - - header.onmousedown = onStart; - container.onmousemove = onDrag; - container.onmouseup = onEnd; -}; - -observe('body', '.modal-header', function(el) { - let header = $(el); - let modal = header.closest('.modal'); - let container = header.closest('.modal-container'); - initDrag( - header[0], modal[0], container[0] - ); -}); diff --git a/web/public/js/post.js b/web/public/js/post.js deleted file mode 100644 index 736fa2b..0000000 --- a/web/public/js/post.js +++ /dev/null @@ -1,38 +0,0 @@ -observe('.post', '.action-load-comments', function(me) { - me.on('click', function() { - let page = me.attr('page'); - if (!page) { - page = '1'; - } - let newPage = Number(page) + 1; - let id = me.attr('postId'); - me.attr('page', newPage + ''); - let url = '/home/comments?page=' + page + '&id=' + id; - $.get(url, function (data) { - if (data === '') { - me.remove(); - } else { - $(me).prepend(data); - } - }); - }); -}); - -observe('#main-content', '#action-load-posts', function(me) { - me.on('click', function () { - let page = me.attr('page'); - if (!page) { - page = '1'; - } - let newPage = Number(page) + 1; - me.attr('page', newPage + ''); - let url = '/home/posts?page=' + page; - $.get(url, function (data) { - if (data === '') { - me.remove(); - } else { - $('#post-container').append(data); - } - }); - }); -}); diff --git a/web/public/js/routes/home.js b/web/public/js/routes/home.js new file mode 100644 index 0000000..e69de29 diff --git a/web/public/js/shared/modal.js b/web/public/js/shared/modal.js new file mode 100644 index 0000000..792cd85 --- /dev/null +++ b/web/public/js/shared/modal.js @@ -0,0 +1,64 @@ +$(document).on('click', ".modal-close", (o) => { + $(o.target).closest('.modal-container').remove(); +}); + +const initDrag = (header, modal, container) => { + let drag = false; + + let mouseX, mouseY, modalX, modalY; + + const onStart = (e) => { + e = e || window.event; + e.preventDefault(); + mouseX = e.clientX; + mouseY = e.clientY; + drag = true; + }; + + const onDrag = (e) => { + e = e || window.event; + e.preventDefault(); + if (!drag) { + return; + } + modalX = mouseX - e.clientX; + modalY = mouseY - e.clientY; + mouseX = e.clientX; + mouseY = e.clientY; + + let posX = (modal.offsetLeft - modalX), + posY = (modal.offsetTop - modalY); + + let minX = modal.offsetWidth / 2, + minY = modal.offsetHeight / 2; + + let maxX = container.offsetWidth - minX, + maxY = container.offsetHeight - minY; + + posX = Math.max(minX, Math.min(maxX, posX)); + posY = Math.max(minY, Math.min(maxY, posY)); + + posX = posX / container.offsetWidth * 100; + posY = posY / container.offsetHeight * 100; + + modal.style.left = posX + "%"; + modal.style.top = posY + "%"; + }; + + const onEnd = () => { + drag = false; + }; + + header.onmousedown = onStart; + container.onmousemove = onDrag; + container.onmouseup = onEnd; +}; + +observe('body', '.modal-header', function(el) { + let header = $(el); + let modal = header.closest('.modal'); + let container = header.closest('.modal-container'); + initDrag( + header[0], modal[0], container[0] + ); +}); diff --git a/web/public/js/shared/post.js b/web/public/js/shared/post.js new file mode 100644 index 0000000..afbeaf0 --- /dev/null +++ b/web/public/js/shared/post.js @@ -0,0 +1,38 @@ +observe('#main-content', '.action-load-comments', function(me) { + me.on('click', function() { + let page = me.attr('page'); + if (!page) { + page = '1'; + } + let newPage = Number(page) + 1; + let id = me.attr('postId'); + me.attr('page', newPage + ''); + let url = '/home/comments?page=' + page + '&id=' + id; + $.get(url, function (data) { + if (data === '') { + me.remove(); + } else { + $(me).prepend(data); + } + }); + }); +}); + +observe('#main-content', '#action-load-posts', function(me) { + me.on('click', function () { + let page = me.attr('page'); + if (!page) { + page = '1'; + } + let newPage = Number(page) + 1; + me.attr('page', newPage + ''); + let url = '/home/posts?page=' + page; + $.get(url, function (data) { + if (data === '') { + me.remove(); + } else { + $('#post-container').append(data); + } + }); + }); +}); -- cgit v1.2.3-freya