diff options
-rw-r--r-- | .browserslistrc | 1 | ||||
-rw-r--r-- | src/main/assets/embed.js | 4 | ||||
-rw-r--r-- | src/main/assets/scripts.js | 250 |
3 files changed, 68 insertions, 187 deletions
diff --git a/.browserslistrc b/.browserslistrc index 5d6dd745..dd6bc33d 100644 --- a/.browserslistrc +++ b/.browserslistrc @@ -4,4 +4,3 @@ ie_mob >= 7 ios_saf >= 9.3 android >= 4.1 firefox >= 48 -opera >= 12.1 diff --git a/src/main/assets/embed.js b/src/main/assets/embed.js index 739b95f3..0022ae82 100644 --- a/src/main/assets/embed.js +++ b/src/main/assets/embed.js @@ -255,10 +255,10 @@ function getEmbeddableLinkTypes() { div.innerHTML = `<blockquote class="twitter-tweet" data-lang="en"><a href="${url}"></a></blockquote>`; - if (window.twttr) { + if (window['twttr']) { // this will only happen if you embed another set of twitter posts after the twitter script loads (likely never) // https://developer.twitter.com/en/docs/twitter-for-websites/javascript-api/guides/scripting-loading-and-initialization - window.twttr.widgets.load(div); + window['twttr'].widgets.load(div); } else if (!document.head.querySelector ('[src="https://platform.twitter.com/widgets.js\"]')) { // innerHTML cannot insert scripts, so... let script = document.createElement('script'); diff --git a/src/main/assets/scripts.js b/src/main/assets/scripts.js index e801c9be..d053748e 100644 --- a/src/main/assets/scripts.js +++ b/src/main/assets/scripts.js @@ -1,50 +1,24 @@ -require('element-closest/browser'); -require('classlist.js'); -require('formdata-polyfill'); -require('whatwg-fetch'); +import elementClosest from 'element-closest'; +import 'formdata-polyfill'; +import 'classlist.js'; +import 'whatwg-fetch'; import 'core-js/stable'; import { embedLinksToX, embedAll, format } from './embed'; import renderIcons from './icon'; import svg4everybody from 'svg4everybody'; -if (!('remove' in Element.prototype)) { // Firefox <23 - Element.prototype.remove = function() { - if (this.parentNode) { - this.parentNode.removeChild(this); - } - }; -} - -Element.prototype.selectText = function() { - let d = document; - if (d.body.createTextRange) { - let range = d.body.createTextRange(); - range.moveToElementText(this); - range.select(); - } else if (window.getSelection) { - let selection = window.getSelection(); - let rangeSel = d.createRange(); - rangeSel.selectNodeContents(this); - selection.removeAllRanges(); - selection.addRange(rangeSel); - } -}; - +/** + * Autosize textarea + * @param {HTMLTextAreaElement} el textarea element + */ function autosize(el) { - let offset = (!window.opera) - ? (el.offsetHeight - el.clientHeight) - : (el.offsetHeight + parseInt(window.getComputedStyle(el, null).getPropertyValue('border-top-width'))); + let offset = el.offsetHeight - el.clientHeight; - let resize = function(el) { - el.style.height = 'auto'; - el.style.height = (el.scrollHeight + offset) + 'px'; - }; - - if (el.addEventListener) { - el.addEventListener('input', () => resize(el)); - } else if (el.attachEvent) { - el.attachEvent('onkeyup', () => resize(el)); - } + el.addEventListener('input', (ev) => { + const textarea = /** @type HTMLTextAreaElement */ (ev.target); + textarea.style.height = 'auto'; + textarea.style.height = (textarea.scrollHeight + offset) + 'px'; + }); } function evilIcon(name) { @@ -108,7 +82,7 @@ const translations = { function getLang() { return (window.navigator.languages && window.navigator.languages[0]) - || window.navigator.userLanguage + || window.navigator['userLanguage'] || window.navigator.language; } function i18n(key, lang = undefined) { @@ -225,7 +199,7 @@ function updateRepliesCounter() { var replies = Array.from(document.querySelectorAll('#replies>li.reply-new')).length; var wsthread = document.getElementById('wsthread'); if (replies) { - wsthread.textContent = replies; + wsthread.textContent = `${replies}`; wsthread.style.display = 'block'; document.title = '[' + replies + '] ' + pageTitle; } else { @@ -238,33 +212,31 @@ function updateRepliesCounter() { /******************************************************************************/ /******************************************************************************/ +/** + * Submit form on Ctrl+Enter + * @param {HTMLElement} formEl Target form element + * @param {KeyboardEvent} ev Keyboard event + */ function postformListener(formEl, ev) { if (ev.ctrlKey && (ev.keyCode == 10 || ev.keyCode == 13)) { let form = formEl.closest('form'); - if (!form.onsubmit || form.onsubmit()) { - form.querySelector('input[type="submit"]').click(); + if (!form.onsubmit || form.submit()) { + /** @type HTMLInputElement */ (form.querySelector('input[type="submit"]')).click(); } } } + +/** + * Close dialog on Esc + * @param {KeyboardEvent} ev Keyboard event + */ function closeDialogListener(ev) { - ev = ev || window.event; + ev = ev || /** @type KeyboardEvent */ (window.event); if (ev.keyCode == 27) { closeDialog(); } } -function newMessage(evt) { - Array.from(document.querySelectorAll('#newmessage .dialogtxt')).forEach(t => { - t.remove(); - }); - if (document.querySelector('#newmessage textarea').value.length == 0 - && document.querySelector('#newmessage .img').value.length == 0 - && !document.querySelector('#newmessage input[type="file"]')) { - document.querySelector('#newmessage').insertAdjacentHTML('afterbegin', `<p class="dialogtxt">${i18n('postForm.pleaseInputMessageText')}</p>`); - evt.preventDefault(); - } -} - function handleErrors(response) { if (!response.ok) { throw Error(response.statusText); @@ -292,13 +264,13 @@ function showCommentForm(mid, rid) { formTarget.remove(); let form = reply.querySelector('form'); - let submitButton = form.querySelector('input[type="submit"]'); + let submitButton = /** @type HTMLInputElement */ (form.querySelector('input[type="submit"]')); let attachButton = form.querySelector('.msg-comment .attach-photo'); - attachButton.addEventListener('click', e => attachCommentPhoto(e.target)); + attachButton.addEventListener('click', e => attachCommentPhoto(/** @type HTMLDivElement */ (e.target))); - let textarea = form.querySelector('.msg-comment textarea'); - textarea.addEventListener('keypress', e => postformListener(e.target, e)); + let textarea = /** @type HTMLTextAreaElement */ (form.querySelector('.msg-comment textarea')); + textarea.addEventListener('keypress', e => postformListener(/** @type HTMLElement */ (e.target), e)); autosize(textarea); let validateMessage = () => { @@ -324,11 +296,11 @@ function showCommentForm(mid, rid) { if (response.ok) { response.json().then(result => { if (result.newMessage) { - window.location.href = new URL(`${mid}#${result.newMessage.rid}`, window.location.href); + window.location.hash = `#${result.newMessage.rid}`; } else { alert(result.text); } - window.location.reload(true); + window.location.reload(); }); } }).catch(error => { @@ -337,7 +309,7 @@ function showCommentForm(mid, rid) { e.preventDefault(); }); } - reply.querySelector('.msg-comment textarea').focus(); + /** @type HTMLTextAreaElement */ (reply.querySelector('.msg-comment textarea')).focus(); } function attachInput() { @@ -349,6 +321,10 @@ function attachInput() { return inp; } +/** + * "Attach" button + * @param {HTMLDivElement} div + */ function attachCommentPhoto(div) { let input = div.querySelector('input'); if (input) { @@ -364,48 +340,6 @@ function attachCommentPhoto(div) { } } -function attachMessagePhoto(div) { - var f = div.closest('form'), - finput = f.querySelector('input[type="file"]'); - if (!finput) { - var inp = attachInput(); - inp.style.float = 'left'; - inp.style.width = 0; - inp.style.height = 0; - inp.addEventListener('change', function() { - div.textContent = i18n('postForm.upload') + ' (✓)'; - }); - f.appendChild(inp); - inp.click(); - } else { - finput.remove(); - div.textContent = i18n('postForm.upload'); - } -} - -function showMessageLinksDialog(mid, rid) { - let hlink = window.location.protocol + '//juick.com/' + mid; - let mlink = '#' + mid; - if (rid > 0) { - hlink += '#' + rid; - mlink += '/' + rid; - } - let hlinkenc = encodeURIComponent(hlink); - let html = ` - <div class="dialogshare"> - ${i18n('shareDialog.linkToMessage')}: <div onclick="this.selectText()" class="dialogl">${hlink}</div> - ${i18n('shareDialog.messageNumber')}: <div onclick="this.selectText()" class="dialogl">${mlink}</div> - ${i18n('shareDialog.share')}: - <ul> - <li><a href="https://www.facebook.com/sharer/sharer.php?u=${hlinkenc}" onclick="return openSocialWindow(this)">${evilIcon('ei-sc-facebook')}</a></li> - <li><a href="https://twitter.com/intent/tweet?url=${hlinkenc}" onclick="return openSocialWindow(this)">${evilIcon('ei-sc-twitter')}</a></li> - <li><a href="https://vk.com/share.php?url=${hlinkenc}" onclick="return openSocialWindow(this)">${evilIcon('ei-sc-vk')}</a></li> - </ul> - </div>`; - - openDialog(html); -} - function showPhotoDialog(fname) { let width = window.innerWidth; let height = window.innerHeight; @@ -421,21 +355,6 @@ function showPhotoDialog(fname) { } } -function openPostDialog() { - let newmessageTemplate = ` - <form id="newmessage" action="/post" method="post" enctype="multipart/form-data"> - <textarea name="body" placeholder="${i18n('postForm.newMessage')}"></textarea> - <div> - <input class="img" name="img" placeholder="${i18n('postForm.imageLink')} (${i18n('postForm.imageFormats')})"/> - ${i18n('postForm.or')} <a href="#">${i18n('postForm.upload')}</a><br/> - <input id="tags_input" class="tags" name="tags" placeholder="${i18n('postForm.tags')}"/><br/> - <input type="submit" class="subm Button" value="${i18n('postForm.submit')}"/> - </div> - </form> - `; - return openDialog(newmessageTemplate); -} - function openDialog(html, image) { var dialogHtml = ` <div id="dialogt"> @@ -460,24 +379,14 @@ function openDialog(html, image) { } function closeDialog() { - let draft = document.querySelector('#newmessage textarea'); - if (draft) { - window.draft = draft.value; - } document.querySelector('body').classList.remove('dialog-opened'); document.querySelector('#dialogb').remove(); document.querySelector('#dialogt').remove(); } -function openSocialWindow(a) { - var w = window.open(a.href, 'juickshare', 'width=640,height=400'); - if (window.focus) { w.focus(); } - return false; -} - function checkUsername() { var uname = document.querySelector('#username').textContent, - style = document.querySelector('#username').style; + style = /** @type HTMLElement */ (document.querySelector('#username')).style; fetch('/api/users?uname=' + uname) .then(handleErrors) .then(function() { @@ -546,7 +455,7 @@ function subscribeMessage(e, mid) { .then(handleErrors) .then(function(response) { if (response.ok) { - window.location.reload(true); + window.location.reload(); } else { alert('Something went wrong :('); } @@ -559,19 +468,6 @@ function subscribeMessage(e, mid) { /******************************************************************************/ -function setPopular(e, mid, popular) { - fetch('/api/messages/set_popular?mid=' + mid - + '&popular=' + popular - + '&hash=' + document.getElementById('body').getAttribute('data-hash'), { - credentials: 'same-origin' - }) - .then(handleErrors) - .then(function() { - e.closest('article').append(resultMessage('OK!')); - }); - return false; -} - function setPrivacy(e, mid) { fetch('/api/messages/set_privacy?mid=' + mid + '&hash=' + document.getElementById('body').getAttribute('data-hash'), { @@ -636,7 +532,8 @@ function ready(fn) { } } -ready(function() { +ready(() => { + elementClosest(window); Array.from(document.querySelectorAll('textarea')).forEach((ta) => { autosize(ta); }); @@ -648,21 +545,21 @@ ready(function() { e.target.removeEventListener('click', insertPMButtons); e.preventDefault(); }; - Array.from(document.querySelectorAll('textarea.replypm')).forEach(function(e) { + /** @type HTMLTextAreaElement[] */ (Array.from(document.querySelectorAll('textarea.replypm'))).forEach(function(e) { e.addEventListener('click', insertPMButtons); e.addEventListener('keypress', function(e) { - postformListener(e.target, e); + postformListener(/** @type HTMLElement */ (e.target), e); }); }); - Array.from(document.querySelectorAll('#postmsg textarea')).forEach(function(e) { + /** @type HTMLTextAreaElement[] */ (Array.from(document.querySelectorAll('#postmsg textarea'))).forEach(function(e) { e.addEventListener('keypress', function(e) { - postformListener(e.target, e); + postformListener(/** @type HTMLElement */ (e.target), e); }); }); var content = document.getElementById('content'); if (content) { - var pageMID = content.getAttribute('data-mid'); + var pageMID = +content.getAttribute('data-mid'); if (pageMID > 0) { Array.from(document.querySelectorAll('li.msg')).forEach(li => { let showReplyFormBtn = li.querySelector('.a-thread-comment'); @@ -675,10 +572,10 @@ ready(function() { }); let opMessage = document.querySelector('.msgthread'); if (opMessage) { - let replyTextarea = opMessage.querySelector('textarea.reply'); + let replyTextarea = /** @type HTMLTextAreaElement */ (opMessage.querySelector('textarea.reply')); if (replyTextarea) { replyTextarea.addEventListener('focus', e => showCommentForm(pageMID, 0)); - replyTextarea.addEventListener('keypress', e => postformListener(e.target, e)); + replyTextarea.addEventListener('keypress', e => postformListener(/** @type HTMLElement */ (e.target), e)); if (!window.location.hash) { replyTextarea.focus(); } @@ -687,7 +584,7 @@ ready(function() { } } - var postmsg = document.getElementById('postmsg'); + var postmsg = /** @type HTMLFormElement */(document.getElementById('postmsg')); if (postmsg) { Array.from(document.querySelectorAll('a')).filter(t => t.href.indexOf('?') >= 0).forEach(t => { t.addEventListener('click', e => { @@ -709,7 +606,7 @@ ready(function() { if (response.ok) { response.json().then(result => { if (result.newMessage) { - window.location = new URL(`/m/${result.newMessage.mid}`, window.location.href); + window.location.href = new URL(`/m/${result.newMessage.mid}`, window.location.href).href; } else { alert(result.text); } @@ -723,7 +620,7 @@ ready(function() { e.preventDefault(); }); } - Array.from(document.querySelectorAll('.pmmsg')).forEach(pmmsg => { + /** @type HTMLFormElement[] */ (Array.from(document.querySelectorAll('.pmmsg'))).forEach(pmmsg => { pmmsg.addEventListener('submit', e => { let formData = new FormData(pmmsg); fetch('/api/pm' + '?hash=' + document.getElementById('body').getAttribute('data-hash'), { @@ -735,7 +632,7 @@ ready(function() { if (response.ok) { response.json().then(result => { if (result.to) { - window.location = new URL('/pm/sent', window.location.href); + window.location.href = new URL('/pm/sent', window.location.href).href; } else { alert('Something went wrong :('); } @@ -750,38 +647,23 @@ ready(function() { }); }); - Array.from(document.querySelectorAll('.msg-menu')).forEach(function(el) { - el.addEventListener('click', function(e) { - var reply = e.target.closest('li'); - var rid = reply ? parseInt(reply.id) : 0; - var message = e.target.closest('section'); - var mid = message.getAttribute('data-mid') || e.target.closest('article').getAttribute('data-mid'); - showMessageLinksDialog(mid, rid); - e.preventDefault(); - }); - }); Array.from(document.querySelectorAll('.l .a-privacy')).forEach(function(e) { e.addEventListener('click', function(e) { setPrivacy( e.target, - e.target.closest('article').getAttribute('data-mid')); + /** @type HTMLElement */(e.target).closest('article').getAttribute('data-mid')); e.preventDefault(); }); }); Array.from(document.querySelectorAll('.ir a[data-fname], .msg-media a[data-fname]')).forEach(function(el) { el.addEventListener('click', function(e) { - let fname = e.target.closest('[data-fname]').getAttribute('data-fname'); + let fname = /** @type HTMLElement */ (e.target).closest('[data-fname]').getAttribute('data-fname'); if (!showPhotoDialog(fname)) { e.preventDefault(); } }); }); - Array.from(document.querySelectorAll('.social a')).forEach(function(e) { - e.addEventListener('click', function(e) { - openSocialWindow(e.target); - e.preventDefault(); - }); - }); + var username = document.getElementById('username'); if (username) { username.addEventListener('blur', function() { @@ -793,7 +675,7 @@ ready(function() { e.addEventListener('click', function(e) { likeMessage( e.target, - e.target.closest('article').getAttribute('data-mid')); + /** @type HTMLElement */(e.target).closest('article').getAttribute('data-mid')); e.preventDefault(); }); }); @@ -814,12 +696,12 @@ ready(function() { var unfoldall = document.getElementById('unfoldall'); if (unfoldall) { unfoldall.addEventListener('click', function(e) { - Array.from(document.querySelectorAll('#replies>li')).forEach(function(e) { - e.style.display = 'block'; - }); - Array.from(document.querySelectorAll('#replies .msg-comments')).forEach(function(e) { - e.style.display = 'none'; - }); + /** @type HTMLElement[] */ (Array.from(document.querySelectorAll('#replies>li'))).forEach(function(e) { + e.style.display = 'block'; + }); + /** @type HTMLElement[] */ (Array.from(document.querySelectorAll('#replies .msg-comments'))).forEach(function(e) { + e.style.display = 'none'; + }); e.preventDefault(); }); } @@ -867,7 +749,7 @@ ready(function() { } }); let location = window.location.href; - Array.from(document.querySelectorAll('#header_wrapper a')).forEach(el => { + /** @type HTMLLinkElement[] */ (Array.from(document.querySelectorAll('#header_wrapper a'))).forEach(el => { if (el.href === location) { el.classList.add('active'); el.setAttribute('disabled', 'disabled'); |