var autosize = require('autosize'); require('whatwg-fetch'); require('element-closest'); require('classlist.js'); 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; var ws, pageTitle; function initWS() { var content = document.getElementById('content'); if (!content) { return } var pageMID = content.getAttribute('data-mid'); if (!pageMID) { return } var url = (window.location.protocol === 'https:' ? 'wss' : 'ws') + ':' + (typeof juickDebug !== 'undefined' ? '//ws.juick.com/_replies' : ('//ws.juick.com/' + pageMID)), hash = document.getElementById('body').getAttribute('data-hash'); if (hash) { url += '?hash=' + hash; } 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); 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 isTreeMode() { // relies on UserThread.printReplies implementation TODO keep this in cookie or something return document.querySelector('.title2-right > a').href.match(/\?view=(\w+)/)[1] == 'list'; } function wsIncomingReply(msg) { var li = document.createElement('li'); li.setAttribute('class', 'msg reply-new'); li.setAttribute('id', msg.rid); li.addEventListener('click', newReply); li.addEventListener('mouseover', newReply); var msgAvatar = document.createElement('div'); msgAvatar.setAttribute('class', 'msg-avatar'); var msgAvatarLink = document.createElement('a'); msgAvatarLink.setAttribute('href', '/' + msg.user.uname + '/'); var msgAvatarImg = document.createElement('img'); msgAvatarImg.setAttribute('src', '//i.juick.com/a/' + msg.user.uid + '.png'); msgAvatarLink.appendChild(msgAvatarImg); msgAvatar.appendChild(msgAvatarLink); var msgCont = document.createElement('div'); msgCont.setAttribute('class', 'msg-cont'); var msgMenu = document.createElement('div'); msgMenu.setAttribute('class', 'msg-menu'); msgCont.appendChild(msgMenu); var msgMenuLink = document.createElement('a'); msgMenuLink.setAttribute('href', '#'); msgMenuLink.addEventListener('click', function (e) { showMessageLinksDialog(msg.mid, msg.rid); e.preventDefault(); }); msgMenu.appendChild(msgMenuLink); var msgHeader = document.createElement('div'); msgHeader.setAttribute('class', 'msg-header'); var msgHeaderLink = document.createElement('a'); msgHeaderLink.setAttribute('href', '/' + msg.user.uname + '/'); msgHeaderLink.textContent = '@' + msg.user.uname + ':'; msgHeader.appendChild(msgHeaderLink); var msgTimestamp = document.createElement('div'); msgTimestamp.setAttribute('class', 'msg-ts'); var msgTimestampLink = document.createElement('a'); msgTimestampLink.setAttribute('href', '/' + msg.mid + '#' + msg.rid); msgTimestampLink.setAttribute('title', msg.timestamp + ' GMT'); msgTimestampLink.textContent = msg.timestamp; msgTimestamp.appendChild(msgTimestampLink); var msgTxt = document.createElement('div'); msgTxt.setAttribute('class', 'msg-txt'); var msgLinks = document.createElement('div'); msgLinks.setAttribute('class', 'msg-links'); var msgNum = '/' + msg.rid; if (msg.replyto > 0) { msgNum += ' в ответ на <a href="#' + msg.replyto + '">/' + msg.replyto + '</a>'; } msgLinks.innerHTML = msgNum + ' · '; var msgLinksLink = document.createElement('a'); msgLinksLink.setAttribute('href', '#'); msgLinksLink.textContent = 'Ответить'; msgLinksLink.addEventListener('click', function (e) { showCommentForm(msg.mid, msg.rid); e.preventDefault(); }); msgLinks.appendChild(msgLinksLink); var msgComment = document.createElement('div'); msgComment.setAttribute('class', 'msg-comment'); msgComment.style.display = 'none'; msgHeader.appendChild(msgAvatar); msgHeader.appendChild(msgMenu); msgHeader.appendChild(msgTimestamp); msgCont.appendChild(msgHeader); msgCont.appendChild(msgTxt); msgCont.appendChild(msgLinks); msgCont.appendChild(msgComment); li.appendChild(msgCont); li.querySelector('.msg-txt').textContent = msg.body; if (isTreeMode() && (msg.replyto > 0)) { var p = document.getElementById(msg.replyto); var m = parseInt(p.style.marginLeft) + 20; while (p.nextElementSibling && (parseInt(p.nextElementSibling.style.marginLeft) >= m)) p = p.nextElementSibling; li.style.marginLeft = m + 'px'; p.parentNode.insertBefore(li, p.nextSibling); } else { 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.childNodes[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) { var form = formEl.closest('form'); if (ev.ctrlKey && (ev.keyCode == 10 || ev.keyCode == 13)) { if (!form.onsubmit || form.onsubmit()) { form.submit(); } } } function unfoldPostForm() { if (window.location.pathname === '/' && window.location.hash === '#post') { document.querySelector('#newmessage>div').style.display = 'block'; var ta = document.querySelector('#newmessage textarea'); ta.style.minHeight = '70px'; ta.focus(); } } function newMessage() { if (document.querySelector('#newmessage textarea').value.length == 0) { openDialog('<p class="dialogtxt">Пожалуйста, введите текст сообщения</p>'); return false; } return true; } function showMoreReplies(el, id) { var foldedReplies = el.closest('li').querySelector('.msg-comments'); if (!foldedReplies) { return } foldedReplies.style.display = 'none'; var replies = document.querySelectorAll('#replies>li'), flagshow = 0, i = 0; for (; i < replies.length; i += 1) { if (flagshow == 1) { if (replies[i].style.display == 'none') { replies[i].style.display = 'block'; } else { break; } } if (replies[i].id == id) { flagshow = 1; } } return false; } function replyForm(mid, rid) { var form = document.createElement('form'); form.setAttribute('action', '/comment'); form.setAttribute('method', 'POST'); form.setAttribute('enctype', 'multipart/form-data'); var input = document.createElement('input'); input.setAttribute('type', 'hidden'); input.setAttribute('name', 'mid'); input.setAttribute('value', mid); form.appendChild(input); if (rid) { var inputRid = document.createElement('input'); inputRid.setAttribute('type', 'hidden'); inputRid.setAttribute('name', 'rid'); inputRid.setAttribute('value', rid); form.appendChild(inputRid); } return form; } function taWrapper() { var txtarea = document.createElement('textarea'); txtarea.setAttribute('name', 'body'); txtarea.setAttribute('rows', 1); txtarea.setAttribute('class', 'reply narrow'); txtarea.setAttribute('placeholder', 'Написать комментарий...'); var txtKeypress = function (e) { postformListener(e.target, e); }; txtarea.addEventListener('keypress', txtKeypress); var wrapper = document.createElement('div'); wrapper.setAttribute('class', 'ta-wrapper'); wrapper.appendChild(txtarea); var att = document.createElement('div'); att.setAttribute('class', 'attach-photo'); att.addEventListener('click', function () { attachCommentPhoto(this); }); wrapper.appendChild(att); return wrapper; } function showCommentForm(mid, rid) { var reply = document.getElementById(rid); if (reply && !reply.querySelector('textarea')) { var c = reply.querySelector('div.msg-cont > .msg-comment'), newNode = c.cloneNode(true), form = replyForm(mid, rid); form.appendChild(newNode); newNode.appendChild(taWrapper()); var subm = document.createElement('input'); subm.setAttribute('type', 'submit'); subm.setAttribute('value', 'OK'); newNode.appendChild(subm); c.parentNode.insertBefore(form, c); c.remove(); } var commentBlock = reply.querySelector('div.msg-cont > form > div.msg-comment'); commentBlock.style.display = 'block'; var commentText = commentBlock.querySelector('textarea'); if (commentText) { autosize(commentText); commentText.focus(); } } function showCommentFooter(e, mid, rid) { var a = e.closest('article'); if (!a.querySelector('footer.comm')) { var form = replyForm(mid, rid), footer = document.createElement('footer'); footer.setAttribute('class', 'comm'); footer.appendChild(taWrapper()); var subm = document.createElement('input'); subm.setAttribute('type', 'submit'); subm.setAttribute('value', 'OK'); footer.appendChild(subm); form.appendChild(footer); a.appendChild(form); autosize(a.querySelector('textarea')); } a.querySelector('textarea').focus(); } function attachInput() { var 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) { if (div.children.length === 0) { var inp = attachInput(); inp.addEventListener('change', function () { inp.parentNode.classList.add('attach-photo-active'); }); inp.click(); div.appendChild(inp); } else { div.innerHTML = null; div.classList.add('attach-photo'); } } 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 = 'загрузить (✓)'; }); f.appendChild(inp); inp.click(); } else { finput.remove(); div.textContent = 'загрузить'; } } function unfoldReply() { var anchor = window.location.hash.substring(1); if ((0 + anchor) > 0) { var el = document.getElementById(anchor); if (!el) { return } while (el.style.display === 'none') { el = el.previousElementSibling; } showMoreReplies(el, el.getAttribute('id')); window.location.replace(window.location.hash); } } function showMessageLinksDialog(mid, rid) { var hlink = window.location.protocol + '//juick.com/' + mid, mlink = '#' + mid; if (rid > 0) { hlink += '#' + rid; mlink += '/' + rid; } var hlinkenc = encodeURIComponent(hlink), html = '<div class="dialogshare">Ссылка на сообщение:' + '<div onclick="this.selectText()" class="dialogl">' + hlink + '</div>' + 'Номер сообщения:' + '<div onclick="this.selectText()" class="dialogl">' + mlink + '</div>' + 'Поделиться:<ul>' + '<li><a href="https://www.facebook.com/sharer/sharer.php?u=' + hlinkenc + '" onclick="return openSocialWindow(this)"></a></li>' + '<li><a href="https://twitter.com/intent/tweet?url=' + hlinkenc + '" onclick="return openSocialWindow(this)" style="background-position: -32px 0;"></a></li>' + '<li><a href="https://vk.com/share.php?url=' + hlinkenc + '" onclick="return openSocialWindow(this)" style="background-position: -64px 0;"></a></li>' + '<li><a href="https://plus.google.com/share?url=' + hlinkenc + '" onclick="return openSocialWindow(this)" style="background-position: -96px 0;"></a></li>' + '</ul></div>'; openDialog(html); } function showPhotoDialog(fname) { var width = window.innerWidth, height = window.innerHeight * 0.9; if (width < 640) { return true; } else if (width < 1280) { openDialog('<a href="//i.juick.com/photos-1024/' + fname + '"><img src="//i.juick.com/photos-512/' + fname + '"/></a>'); document.querySelector('#dialogw img').style.maxHeight = height + 'px'; return false; } else { openDialog('<a href="//i.juick.com/p/' + fname + '"><img src="//i.juick.com/photos-1024/' + fname + '"/></a>'); document.querySelector('#dialogw img').style.maxHeight = height + 'px'; return false; } } function openDialog(html) { var dhtml = '<table id="dialogt"><tr><td><div id="dialogb"></div><div id="dialogw"><div id="dialogc"></div>' + html + '</div></td></tr></table>'; document.querySelector('body').insertAdjacentHTML('afterbegin', dhtml); document.querySelector('#dialogb').addEventListener('click', closeDialog); document.querySelector('#dialogc').addEventListener('click', closeDialog); } function closeDialog() { 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() { var html = '<div class="dialoglogin"><p>Пожалуйста, представьтесь:' + '<a href="/_fblogin" id="signfb">Facebook</a> ' + '<a href="/_vklogin" id="signvk">ВКонтакте</a></p>' + '<p>Уже зарегистрированы?</p>' + '<form action="/login" method="POST">' + '<input class="signinput" type="text" name="username" placeholder="Имя пользователя"/><br/>' + '<input class="signinput" type="password" name="password" placeholder="Пароль"/><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('Are you sure?')) { fetch('//juick.com/like?mid=' + mid, { method: 'POST', credentials: 'same-origin' }) .then(function (response) { if (response.ok) { e.closest('article').appendChild(resultMessage('OK!')); } }) .catch(function () { e.closest('article').appendChild(resultMessage('Ошибка')); }); } 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; } /******************************************************************************/ Element.prototype.selectText = function () { var d = document; if (d.body.createTextRange) { var range = d.body.createTextRange(); range.moveToElementText(this); range.select(); } else if (window.getSelection) { var selection = window.getSelection(); var rangeSel = d.createRange(); rangeSel.selectNodeContents(this); selection.removeAllRanges(); selection.addRange(rangeSel); } }; function ready(fn) { if (document.readyState != 'loading') { fn(); } else { document.addEventListener('DOMContentLoaded', fn); } } ready(function () { autosize(document.querySelectorAll('textarea')); var insertButtons = function (e) { var textarea = e.target; textarea.classList.add('narrow'); var att = document.createElement('div'); att.classList.add('attach-photo'); att.addEventListener('click', function(e) { attachCommentPhoto(e.target); }); textarea.parentNode.insertBefore(att, textarea.nextSibling); textarea.parentNode.insertAdjacentHTML('afterend', '<input type="submit" value="OK"/>'); textarea.removeEventListener('click', insertButtons); e.preventDefault(); }; document.querySelectorAll('textarea.reply').forEach(function(e) { e.addEventListener('click', insertButtons); e.addEventListener('keypress', function(e) { postformListener(e.target, e); }); }); 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); }); var content = document.getElementById('content'); if (content) { var pageMID = content.getAttribute('data-mid'); if (pageMID > 0) { document.querySelectorAll('.msg-comments').forEach(function(e) { e.addEventListener('click', function (e) { var rid = e.target.closest('li').id; showMoreReplies(e.target, rid); e.preventDefault(); }); }); document.querySelectorAll('.a-thread-comment').forEach(function(e) { e.addEventListener('click', function (e) { var rid = e.target.closest('li').id; showCommentForm(pageMID, rid); e.preventDefault(); }); }); } } document.querySelectorAll('.msg-menu a').forEach(function(el) { el.addEventListener('click', function(e) { showMessageLinksDialog( e.target.closest('section').getAttribute('data-mid'), parseInt(e.target.closest('li').id)); // rid e.preventDefault(); }); }); document.querySelectorAll('.l .a-comment').forEach(function(e) { e.addEventListener('click', function (e) { showCommentFooter( e.target, e.target.closest('article').getAttribute('data-mid')); 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('.l .a-popular-plus').forEach(function(e) { e.addEventListener('click', function (e) { setPopular( e.target, e.target.closest('article').getAttribute('data-mid'), 2); e.preventDefault(); }); }); document.querySelectorAll('.l .a-popular-minus').forEach(function(e) { e.addEventListener('click', function (e) { setPopular( e.target, e.target.closest('article').getAttribute('data-mid'), -1); e.preventDefault(); }); }); document.querySelectorAll('.l .a-popular-delete').forEach(function(e) { e.addEventListener('click', function (e) { setPopular( e.target, e.target.closest('article').getAttribute('data-mid'), -2); e.preventDefault(); }); }); document.querySelectorAll('.ir a').forEach(function(e) { e.addEventListener('click', function (e) { var 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(); }); }); document.querySelectorAll('.attach-photo').forEach(function(el) { el.addEventListener('click', function(e) { attachCommentPhoto(e.target); }); }); 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(); }); } var newMessageBlock = document.getElementById('newmessage'); if (newMessageBlock) { var form = newMessageBlock.parentNode; form.addEventListener('submit', newMessage); newMessageBlock.querySelector('textarea').addEventListener('click', function(e) { var parent = e.target.parentNode; parent.querySelector('div').style.display = 'block'; e.target.style.minHeight = '70px'; e.target.addEventListener('keypress', function(e) { postformListener(e.target, e); }); }); newMessageBlock.querySelector('a').addEventListener('click', function(e) { attachMessagePhoto(e.target); }); } document.querySelectorAll('article').forEach(function(article) { if (Array.prototype.some.call( article.querySelectorAll('.u a'), function (a) { return a.textContent === 'NSFW'; } )) { var img = article.querySelector('.ir img'); if (img) { img.style.opacity = 0.05; img.addEventListener('mouseover', function(e) { e.target.style.opacity = 1; }); img.addEventListener('mouseout', function(e) { e.target.style.opacity = 0.05; }); } } }); unfoldPostForm(); unfoldReply(); initWS(); window.addEventListener('hashchange', unfoldPostForm); window.addEventListener('hashchange', unfoldReply); window.addEventListener('pagehide', wsShutdown); });