aboutsummaryrefslogtreecommitdiff
path: root/juick-server/src/main/assets/scripts.js
diff options
context:
space:
mode:
Diffstat (limited to 'juick-server/src/main/assets/scripts.js')
-rw-r--r--juick-server/src/main/assets/scripts.js805
1 files changed, 805 insertions, 0 deletions
diff --git a/juick-server/src/main/assets/scripts.js b/juick-server/src/main/assets/scripts.js
new file mode 100644
index 00000000..54e7958e
--- /dev/null
+++ b/juick-server/src/main/assets/scripts.js
@@ -0,0 +1,805 @@
+require('whatwg-fetch');
+require('element-closest');
+require('classlist.js');
+require('url-search-params-polyfill');
+let Awesomplete = require('awesomplete');
+import * as killy from './embed';
+
+if (!('remove' in Element.prototype)) { // Firefox <23
+ Element.prototype.remove = function () {
+ if (this.parentNode) {
+ this.parentNode.removeChild(this);
+ }
+ };
+}
+
+NodeList.prototype.forEach = Array.prototype.forEach;
+HTMLCollection.prototype.forEach = Array.prototype.forEach;
+
+NodeList.prototype.filter = Array.prototype.filter;
+HTMLCollection.prototype.filter = Array.prototype.filter;
+
+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);
+ }
+};
+
+function autosize(el) {
+ let offset = (!window.opera)
+ ? (el.offsetHeight - el.clientHeight)
+ : (el.offsetHeight + parseInt(window.getComputedStyle(el, null).getPropertyValue('border-top-width')));
+
+ 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));
+ }
+}
+
+function evilIcon(name) {
+ return `<div class="icon icon--${name}"><svg class="icon__cnt"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#${name}-icon"></use></svg></div>`;
+}
+
+/* eslint-disable only-ascii/only-ascii */
+const translations = {
+ 'en': {
+ 'message.inReplyTo': 'in reply to',
+ 'message.reply': 'Reply',
+ 'message.likeThisMessage?': 'Recommend this message?',
+ 'postForm.pleaseInputMessageText': 'Please input message text',
+ 'postForm.upload': 'Upload',
+ 'postForm.newMessage': 'New message...',
+ 'postForm.imageLink': 'Link to image',
+ 'postForm.imageFormats': 'JPG/PNG, up to 10 MB',
+ 'postForm.or': 'or',
+ 'postForm.tags': 'Tags (space separated)',
+ 'postForm.submit': 'Send',
+ 'comment.writeComment': 'Write a comment...',
+ 'shareDialog.linkToMessage': 'Link to message',
+ 'shareDialog.messageNumber': 'Message number',
+ 'shareDialog.share': 'Share',
+ 'loginDialog.pleaseIntroduceYourself': 'Please introduce yourself',
+ 'loginDialog.registeredAlready': 'Registered already?',
+ 'loginDialog.username': 'Username',
+ 'loginDialog.password': 'Password',
+ 'loginDialog.facebook': 'Login with Facebook',
+ 'loginDialog.vk': 'Login with VK',
+ 'loginDialog.email': 'Registration',
+ 'error.error': 'Error'
+ },
+ 'ru': {
+ 'message.inReplyTo': 'в ответ на',
+ 'message.reply': 'Ответить',
+ 'message.likeThisMessage?': 'Рекомендовать это сообщение?',
+ 'postForm.pleaseInputMessageText': 'Пожалуйста, введите текст сообщения',
+ 'postForm.upload': 'загрузить',
+ 'postForm.newMessage': 'Новое сообщение...',
+ 'postForm.imageLink': 'Ссылка на изображение',
+ 'postForm.imageFormats': 'JPG/PNG, до 10Мб',
+ 'postForm.or': 'или',
+ 'postForm.tags': 'Теги (через пробел)',
+ 'postForm.submit': 'Отправить',
+ 'comment.writeComment': 'Написать комментарий...',
+ 'shareDialog.linkToMessage': 'Ссылка на сообщение',
+ 'shareDialog.messageNumber': 'Номер сообщения',
+ 'shareDialog.share': 'Поделиться',
+ 'loginDialog.pleaseIntroduceYourself': 'Пожалуйста, представьтесь',
+ 'loginDialog.registeredAlready': 'Уже зарегистрированы?',
+ 'loginDialog.username': 'Имя пользователя',
+ 'loginDialog.password': 'Пароль',
+ 'loginDialog.facebook': 'Войти через Facebook',
+ 'loginDialog.vk': 'Войти через ВКонтакте',
+ 'loginDialog.email': 'Регистрация',
+ 'error.error': 'Ошибка'
+ }
+};
+/* eslint-enable only-ascii/only-ascii */
+
+function getLang() {
+ return (window.navigator.languages && window.navigator.languages[0])
+ || window.navigator.userLanguage
+ || window.navigator.language;
+}
+function i18n(key, lang = undefined) {
+ const fallbackLang = 'ru';
+ lang = lang || getLang().split('-')[0];
+ return (translations[lang] && translations[lang][key])
+ || translations[fallbackLang][key]
+ || key;
+}
+
+var ws,
+ pageTitle;
+
+function initWS() {
+ let url = (window.location.protocol === 'https:' ? 'wss' : 'ws') + ':'
+ + '//api.juick.com/ws/';
+ let hash = document.getElementById('body').getAttribute('data-hash');
+ if (hash) {
+ url += '?hash=' + hash;
+ } else {
+ let content = document.getElementById('content');
+ if (content) {
+ let pageMID = content.getAttribute('data-mid');
+ if (pageMID) {
+ url += pageMID;
+ }
+ }
+ }
+
+ ws = new WebSocket(url);
+ ws.onopen = function () {
+ console.log('online');
+ if (!document.querySelector('#wsthread')) {
+ var d = document.createElement('div');
+ d.id = 'wsthread';
+ d.addEventListener('click', nextReply);
+ document.querySelector('body').appendChild(d);
+ pageTitle = document.title;
+ }
+ };
+ ws.onclose = function () {
+ console.log('offline');
+ ws = false;
+ setTimeout(function () {
+ initWS();
+ }, 2000);
+ };
+ ws.onmessage = function (msg) {
+ if (msg.data == ' ') {
+ ws.send(' ');
+ } else {
+ try {
+ var jsonMsg = JSON.parse(msg.data);
+ console.log('data: ' + msg.data);
+ if (jsonMsg.service) {
+ return;
+ }
+ wsIncomingReply(jsonMsg);
+ } catch (err) {
+ console.log(err);
+ }
+ }
+ };
+ setInterval(wsSendKeepAlive, 90000);
+}
+
+function wsSendKeepAlive() {
+ if (ws) {
+ ws.send(' ');
+ }
+}
+
+function wsShutdown() {
+ if (ws) {
+ ws.onclose = function () { };
+ ws.close();
+ }
+}
+
+function wsIncomingReply(msg) {
+ let content = document.getElementById('content');
+ if (!content) { return; }
+ let pageMID = content.getAttribute('data-mid');
+ if (!pageMID || pageMID != msg.mid) { return; }
+ let msgNum = '/' + msg.rid;
+ if (msg.replyto > 0) {
+ msgNum += ` ${i18n('message.inReplyTo')} <a href="#${msg.replyto}">/${msg.replyto}</a>`;
+ }
+ let photoDiv = (msg.attach == null) ? '' : `
+ <div class="msg-media"><a href="//i.juick.com/p/${msg.mid}-${msg.rid}.${msg.attach}">
+ <img src="//i.juick.com/photos-512/${msg.mid}-${msg.rid}.${msg.attach}"/></a>
+ </div>`;
+ let msgContHtml = `
+ <div class="msg-cont">
+ <div class="msg-header">
+ <a href="/${msg.user.uname}/">${msg.user.uname}</a>:
+ <div class="msg-avatar">
+ <a href="/${msg.user.uname}/"><img src="//i.juick.com/a/${msg.user.uid}.png" alt="${msg.user.uname}"/></a>
+ </div>
+ <div class="msg-ts">
+ <a href="/m/${msg.mid}#${msg.rid}" title="${msg.timestamp}GMT">${msg.timestamp}</a>
+ </div>
+ </div>
+ <div class="msg-txt">${killy.format(msg.body, msg.mid, false)}</div>${photoDiv}
+ <div class="msg-links">${msgNum} &middot; <a class="msg-reply-link" href="#">${i18n('message.reply')}</a></div>
+ <div class="msg-comment-target msg-comment-hidden"></div>
+ </div>`;
+
+ let li = document.createElement('li');
+ li.setAttribute('class', 'msg reply-new');
+ li.setAttribute('id', msg.rid);
+ li.innerHTML = msgContHtml;
+ li.addEventListener('click', newReply);
+ li.addEventListener('mouseover', newReply);
+ li.querySelector('a.msg-reply-link').addEventListener('click', function (e) {
+ showCommentForm(msg.mid, msg.rid);
+ e.preventDefault();
+ });
+
+ killy.embedLinksToX(li.querySelector('.msg-cont'), '.msg-links', '.msg-txt a');
+
+ document.getElementById('replies').appendChild(li);
+
+ updateRepliesCounter();
+}
+
+function newReply(e) {
+ var li = e.target;
+ li.classList.remove('reply-new');
+ li.removeEventListener('click', e);
+ li.removeEventListener('mouseover', e);
+ updateRepliesCounter();
+}
+
+function nextReply() {
+ var li = document.querySelector('#replies>li.reply-new');
+ if (li) {
+ li.classList.remove('reply-new');
+ li.removeEventListener('click', this);
+ li.children[0].scrollIntoView();
+ updateRepliesCounter();
+ }
+}
+
+function updateRepliesCounter() {
+ var replies = document.querySelectorAll('#replies>li.reply-new').length;
+ var wsthread = document.getElementById('wsthread');
+ if (replies) {
+ wsthread.textContent = replies;
+ wsthread.style.display = 'block';
+ document.title = '[' + replies + '] ' + pageTitle;
+ } else {
+ wsthread.style.display = 'none';
+ document.title = pageTitle;
+ }
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+function postformListener(formEl, ev) {
+ if (ev.ctrlKey && (ev.keyCode == 10 || ev.keyCode == 13)) {
+ let form = formEl.closest('form');
+ if (!form.onsubmit || form.onsubmit()) {
+ form.submit();
+ }
+ }
+}
+function closeDialogListener(ev) {
+ ev = ev || window.event;
+ if (ev.keyCode == 27) {
+ closeDialog();
+ }
+}
+
+function newMessage(evt) {
+ 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 showCommentForm(mid, rid) {
+ let reply = document.getElementById(rid);
+ let formTarget = reply.querySelector('div.msg-cont .msg-comment-target');
+ if (formTarget) {
+ let formHtml = `
+ <form action="/comment" method="POST" enctype="multipart/form-data">
+ <input type="hidden" name="mid" value="${mid}">
+ <input type="hidden" name="rid" value="${rid}">
+ <div class="msg-comment">
+ <div class="ta-wrapper">
+ <textarea name="body" rows="1" class="reply" placeholder="${i18n('comment.writeComment')}"></textarea>
+ <div class="attach-photo">${evilIcon('ei-camera')}</div>
+ </div>
+ <input type="submit" value="OK">
+ </div>
+ </form>`;
+ formTarget.insertAdjacentHTML('afterend', formHtml);
+ formTarget.remove();
+
+ let form = reply.querySelector('form');
+ let submitButton = form.querySelector('input[type="submit"]');
+
+ let attachButton = form.querySelector('.msg-comment .attach-photo');
+ attachButton.addEventListener('click', e => attachCommentPhoto(e.target));
+
+ let textarea = form.querySelector('.msg-comment textarea');
+ textarea.addEventListener('keypress', e => postformListener(e.target, e));
+ autosize(textarea);
+
+ let validateMessage = () => {
+ let len = textarea.value.length;
+ if (len > 4096) { return 'Message is too long'; }
+ return '';
+ };
+ form.addEventListener('submit', e => {
+ let validationResult = validateMessage();
+ if (validationResult) {
+ e.preventDefault();
+ alert(validationResult);
+ return false;
+ }
+ submitButton.disabled = true;
+ });
+ }
+ reply.querySelector('.msg-comment textarea').focus();
+}
+
+function attachInput() {
+ let inp = document.createElement('input');
+ inp.setAttribute('type', 'file');
+ inp.setAttribute('name', 'attach');
+ inp.setAttribute('accept', 'image/jpeg,image/png');
+ inp.style.visibility = 'hidden';
+ return inp;
+}
+
+function attachCommentPhoto(div) {
+ let input = div.querySelector('input');
+ if (input) {
+ input.remove();
+ div.classList.remove('attach-photo-active');
+ } else {
+ let newInput = attachInput();
+ newInput.addEventListener('change', function () {
+ div.classList.add('attach-photo-active');
+ });
+ newInput.click();
+ div.appendChild(newInput);
+ }
+}
+
+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;
+ let minDimension = (width < height) ? width : height;
+ if (minDimension < 640) {
+ return true; // no dialog, open the link
+ } else if (minDimension < 1280) {
+ openDialog(`<a href="//i.juick.com/p/${fname}"><img src="//i.juick.com/photos-1024/${fname}"/></a>`, true);
+ return false;
+ } else {
+ openDialog(`<a href="//i.juick.com/p/${fname}"><img src="//i.juick.com/p/${fname}"/></a>`, true);
+ return false;
+ }
+}
+
+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" value="${i18n('postForm.submit')}"/>
+ </div>
+ </form>
+ `;
+ return openDialog(newmessageTemplate);
+}
+
+function openDialog(html, image) {
+ var dialogHtml = `
+ <div id="dialogt">
+ <div id="dialogb"></div>
+ <div id="dialogw">
+ <div id="dialog_header">
+ <div id="dialogc">${evilIcon('ei-close')}</div>
+ </div>
+ ${html}
+ </div>
+ </div>`;
+ let body = document.querySelector('body');
+ body.classList.add('dialog-opened');
+ body.insertAdjacentHTML('afterbegin', dialogHtml);
+ if (image) {
+ let header = document.querySelector('#dialog_header');
+ header.classList.add('header_image');
+ }
+ document.addEventListener('keydown', closeDialogListener);
+ document.querySelector('#dialogb').addEventListener('click', closeDialog);
+ document.querySelector('#dialogc').addEventListener('click', closeDialog);
+}
+
+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;
+ fetch('//api.juick.com/users?uname=' + uname)
+ .then(function () {
+ style.background = '#FFCCCC';
+ })
+ .catch(function () {
+ style.background = '#CCFFCC';
+ });
+}
+
+/******************************************************************************/
+
+function openDialogLogin() {
+ let html = `
+ <div class="dialoglogin">
+ <p>${i18n('loginDialog.pleaseIntroduceYourself')}:</p>
+ <a href="mailto:juick@juick.com?subject=LOGIN" id="signemail">${evilIcon('ei-envelope')}${i18n('loginDialog.email')}</a>
+ <a href="/_fblogin" id="signfb">${evilIcon('ei-sc-facebook')}${i18n('loginDialog.facebook')}</a>
+ <a href="/_vklogin" id="signvk">${evilIcon('ei-sc-vk')}${i18n('loginDialog.vk')}</a>
+ <p>${i18n('loginDialog.registeredAlready')}</p>
+ <form action="/login" method="POST">
+ <input class="signinput" type="text" name="username" placeholder="${i18n('loginDialog.username')}"/><br/>
+ <input class="signinput" type="password" name="password" placeholder="${i18n('loginDialog.password')}"/><br/>
+ <input class="signsubmit" type="submit" value="OK"/>
+ </form>
+ </div>`;
+ openDialog(html);
+ return false;
+}
+
+/******************************************************************************/
+
+function resultMessage(str) {
+ var result = document.createElement('p');
+ result.textContent = str;
+ return result;
+}
+
+function likeMessage(e, mid) {
+ if (confirm(i18n('message.likeThisMessage?'))) {
+ fetch('//api.juick.com/like?mid=' + mid
+ + '&hash=' + document.getElementById('body').getAttribute('data-hash'), {
+ method: 'POST',
+ credentials: 'same-origin'
+ })
+ .then(function (response) {
+ if (response.ok) {
+ e.closest('article').appendChild(resultMessage('OK!'));
+ }
+ })
+ .catch(function () {
+ e.closest('article').appendChild(resultMessage(i18n('error.error')));
+ });
+ }
+ return false;
+}
+
+/******************************************************************************/
+
+function setPopular(e, mid, popular) {
+ fetch('//api.juick.com/messages/set_popular?mid=' + mid
+ + '&popular=' + popular
+ + '&hash=' + document.getElementById('body').getAttribute('data-hash'), {
+ credentials: 'same-origin'
+ })
+ .then(function () {
+ e.closest('article').append(resultMessage('OK!'));
+ });
+ return false;
+}
+
+function setPrivacy(e, mid) {
+ fetch('//api.juick.com/messages/set_privacy?mid=' + mid
+ + '&hash=' + document.getElementById('body').getAttribute('data-hash'), {
+ credentials: 'same-origin'
+ })
+ .then(function () {
+ e.closest('article').append(resultMessage('OK!'));
+ });
+ return false;
+}
+
+function getTags() {
+ fetch('//api.juick.com/tags?hash=' + document.getElementById('body').getAttribute('data-hash'), {
+ credentials: 'same-origin'
+ })
+ .then(response => {
+ return response.json();
+ })
+ .then(json => {
+ let tags = json.map(t => t.tag);
+ let input = document.getElementById('tags_input');
+ new Awesomplete(input, { list: tags });
+ });
+ return false;
+}
+
+function addTag(tag) {
+ document.forms['postmsg'].body.value = '*' + tag + ' ' + document.forms['postmsg'].body.value;
+ return false;
+}
+
+/******************************************************************************/
+
+function ready(fn) {
+ if (document.readyState != 'loading') {
+ fn();
+ } else {
+ document.addEventListener('DOMContentLoaded', fn);
+ }
+}
+
+ready(function () {
+ document.querySelectorAll('textarea').forEach((ta) => {
+ autosize(ta);
+ });
+
+ var insertPMButtons = function (e) {
+ e.target.classList.add('narrowpm');
+ e.target.parentNode.insertAdjacentHTML('afterend', '<input type="submit" value="OK"/>');
+ e.target.removeEventListener('click', insertPMButtons);
+ e.preventDefault();
+ };
+ document.querySelectorAll('textarea.replypm').forEach(function (e) {
+ e.addEventListener('click', insertPMButtons);
+ e.addEventListener('keypress', function (e) {
+ postformListener(e.target, e);
+ });
+ });
+ document.querySelectorAll('#postmsg textarea').forEach(function (e) {
+ e.addEventListener('keypress', function (e) {
+ postformListener(e.target, e);
+ });
+ });
+
+ var content = document.getElementById('content');
+ if (content) {
+ var pageMID = content.getAttribute('data-mid');
+ if (pageMID > 0) {
+ document.querySelectorAll('li.msg').forEach(li => {
+ let showReplyFormBtn = li.querySelector('.a-thread-comment');
+ if (showReplyFormBtn) {
+ showReplyFormBtn.addEventListener('click', function (e) {
+ showCommentForm(pageMID, li.id);
+ e.preventDefault();
+ });
+ }
+ });
+ let opMessage = document.querySelector('.msgthread');
+ if (opMessage) {
+ let replyTextarea = opMessage.querySelector('textarea.reply');
+ if (replyTextarea) {
+ replyTextarea.addEventListener('focus', e => showCommentForm(pageMID, 0));
+ replyTextarea.addEventListener('keypress', e => postformListener(e.target, e));
+ if (!window.location.hash) {
+ replyTextarea.focus();
+ }
+ }
+ }
+ }
+ }
+
+ var postmsg = document.getElementById('postmsg');
+ if (postmsg) {
+ document.querySelectorAll('a').filter(t => t.href.indexOf('?') >= 0).forEach(t => {
+ t.addEventListener('click', e => {
+ let params = new URLSearchParams(t.href.slice(t.href.indexOf('?') + 1));
+ if (params.has('tag')) {
+ addTag(params.get('tag'));
+ e.preventDefault();
+ }
+ });
+ });
+ }
+
+ 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();
+ });
+ });
+ document.querySelectorAll('.l .a-privacy').forEach(function (e) {
+ e.addEventListener('click', function (e) {
+ setPrivacy(
+ e.target,
+ e.target.closest('article').getAttribute('data-mid'));
+ e.preventDefault();
+ });
+ });
+ 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');
+ if (!showPhotoDialog(fname)) {
+ e.preventDefault();
+ }
+ });
+ });
+ 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 () {
+ checkUsername();
+ });
+ }
+
+ document.querySelectorAll('.l .a-like').forEach(function (e) {
+ e.addEventListener('click', function (e) {
+ likeMessage(
+ e.target,
+ e.target.closest('article').getAttribute('data-mid'));
+ e.preventDefault();
+ });
+ });
+ document.querySelectorAll('.a-login').forEach(function (el) {
+ el.addEventListener('click', function (e) {
+ openDialogLogin();
+ e.preventDefault();
+ });
+ });
+ var unfoldall = document.getElementById('unfoldall');
+ if (unfoldall) {
+ unfoldall.addEventListener('click', function (e) {
+ document.querySelectorAll('#replies>li').forEach(function (e) {
+ e.style.display = 'block';
+ });
+ document.querySelectorAll('#replies .msg-comments').forEach(function (e) {
+ e.style.display = 'none';
+ });
+ e.preventDefault();
+ });
+ }
+ document.querySelectorAll('article').forEach(function (article) {
+ if (Array.prototype.some.call(
+ article.querySelectorAll('.msg-tags a'),
+ function (a) {
+ return a.textContent === 'NSFW';
+ }
+ )) {
+ article.classList.add('nsfw');
+ }
+ });
+ initWS();
+
+ window.addEventListener('pagehide', wsShutdown);
+
+ killy.embedAll();
+ var elSelector = 'header',
+ elClassHidden = 'header--hidden',
+ elClassBackground = 'header--background',
+ throttleTimeout = 500,
+ element = document.querySelector(elSelector);
+
+ if (element) {
+
+ var dHeight = 0,
+ wHeight = 0,
+ wScrollCurrent = 0,
+ wScrollBefore = 0,
+ wScrollDiff = 0,
+
+ throttle = function (delay, fn) {
+ var last, deferTimer;
+ return function () {
+ var context = this, args = arguments, now = +new Date;
+ if (last && now < last + delay) {
+ clearTimeout(deferTimer);
+ deferTimer = setTimeout(
+ function () {
+ last = now;
+ fn.apply(context, args);
+ },
+ delay);
+ } else {
+ last = now;
+ fn.apply(context, args);
+ }
+ };
+ };
+
+ window.addEventListener('scroll', throttle(throttleTimeout, function () {
+ dHeight = document.body.offsetHeight;
+ wHeight = window.innerHeight;
+ wScrollCurrent = window.pageYOffset;
+ wScrollDiff = wScrollBefore - wScrollCurrent;
+
+ if (wScrollCurrent <= 0) {
+ // scrolled to the very top; element sticks to the top
+ element.classList.remove(elClassHidden);
+ element.classList.remove(elClassBackground);
+ } else if (wScrollDiff > 0 && element.classList.contains(elClassHidden)) {
+ // scrolled up; element slides in
+ element.classList.remove(elClassHidden);
+ element.classList.add(elClassBackground);
+ } else if (wScrollDiff < 0) {
+ // scrolled down
+ if (wScrollCurrent + wHeight >= dHeight && element.classList.contains(elClassHidden)) {
+ // scrolled to the very bottom; element slides in
+ element.classList.remove(elClassHidden);
+ element.classList.add(elClassBackground);
+ } else {
+ // scrolled down; element slides out
+ element.classList.add(elClassHidden);
+ }
+ }
+
+ wScrollBefore = wScrollCurrent;
+ }));
+ }
+});