From 7aaa3f9a29c280f01c677c918932620be45cdbd7 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Thu, 8 Nov 2018 21:38:27 +0300 Subject: Merge everything into single Spring Boot application --- src/main/assets/scripts.js | 935 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 935 insertions(+) create mode 100644 src/main/assets/scripts.js (limited to 'src/main/assets/scripts.js') diff --git a/src/main/assets/scripts.js b/src/main/assets/scripts.js new file mode 100644 index 00000000..9ee0639e --- /dev/null +++ b/src/main/assets/scripts.js @@ -0,0 +1,935 @@ +require('element-closest'); +require('classlist.js'); +require('url-polyfill'); +require('formdata-polyfill'); +import { embedLinksToX, embedAll, format } 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 `
`; +} + +/* 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 es, pageTitle; + +function initES() { + if (!('EventSource' in window)) { + return; + } + let url = '/api/events'; + let hash = document.getElementById('body').getAttribute('data-hash'); + if (hash) { + url += '?hash=' + hash; + } + + es = new EventSource(url); + es.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; + } + }; + es.addEventListener('msg', msg => { + try { + var jsonMsg = JSON.parse(msg.data); + console.log('data: ' + msg.data); + if (jsonMsg.service) { + return; + } + wsIncomingReply(jsonMsg); + } catch (err) { + console.log(err); + } + }); +} + +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')} /${msg.replyto}`; + } + let photoDiv = (msg.attach == null) ? '' : ` +
+ +
`; + let msgContHtml = ` +
+
+ ${msg.user.uname}: +
+ ${msg.user.uname} +
+ +
+
${format(msg.body, msg.mid, false)}
${photoDiv} + +
+
`; + + 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(); + }); + + 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.querySelector('input[type="submit"]').click(); + } + } +} +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', `

${i18n('postForm.pleaseInputMessageText')}

`); + evt.preventDefault(); + } +} + +function handleErrors(response) { + if (!response.ok) { + throw Error(response.statusText); + } + return response; +} + +function showCommentForm(mid, rid) { + let reply = document.getElementById(rid); + let formTarget = reply.querySelector('div.msg-cont .msg-comment-target'); + if (formTarget) { + let formHtml = ` +
+ + +
+
+ +
${evilIcon('ei-camera')}
+
+ +
+
`; + 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; + let formData = new FormData(form); + fetch('/api/comment' + '?hash=' + document.getElementById('body').getAttribute('data-hash'), { + method: 'POST', + body: formData, + credentials: 'omit' + }).then(handleErrors) + .then(response => { + if (response.ok) { + response.json().then(result => { + if (result.newMessage) { + window.location.href = new URL(`${mid}#${result.newMessage.rid}`, window.location.href); + } else { + alert(result.text); + } + window.location.reload(true); + }); + } + }).catch(error => { + alert(error.message); + }); + e.preventDefault(); + }); + } + 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 = ` +
+ ${i18n('shareDialog.linkToMessage')}:
${hlink}
+ ${i18n('shareDialog.messageNumber')}:
${mlink}
+ ${i18n('shareDialog.share')}: + +
`; + + 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(``, true); + return false; + } else { + openDialog(``, true); + return false; + } +} + +function openPostDialog() { + let newmessageTemplate = ` +
+ +
+ + ${i18n('postForm.or')} ${i18n('postForm.upload')}
+
+ +
+
+ `; + return openDialog(newmessageTemplate); +} + +function openDialog(html, image) { + var dialogHtml = ` +
+
+
+
+
${evilIcon('ei-close')}
+
+ ${html} +
+
`; + 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/users?uname=' + uname) + .then(handleErrors) + .then(function() { + style.background = '#FFCCCC'; + }) + .catch(function() { + style.background = '#CCFFCC'; + }); +} + +/******************************************************************************/ + +function openDialogLogin() { + let html = ` +
+

${i18n('loginDialog.pleaseIntroduceYourself')}:

+ ${evilIcon('ei-envelope')}${i18n('loginDialog.email')} + ${evilIcon('ei-sc-facebook')}${i18n('loginDialog.facebook')} + ${evilIcon('ei-sc-vk')}${i18n('loginDialog.vk')} +

${i18n('loginDialog.registeredAlready')}

+
+
+
+ +
+
`; + 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/like?mid=' + mid + + '&hash=' + document.getElementById('body').getAttribute('data-hash'), { + method: 'POST', + credentials: 'omit' + }) + .then(handleErrors) + .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 subscribeMessage(e, mid) { + fetch('/api/subscribe?mid=' + mid + + '&hash=' + document.getElementById('body').getAttribute('data-hash'), { + method: 'POST', + credentials: 'omit' + }) + .then(handleErrors) + .then(function(response) { + if (response.ok) { + window.location.reload(true); + } else { + alert('Something went wrong :('); + } + }) + .catch(error => { + alert(error.message); + }); + return false; +} + +/******************************************************************************/ + +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'), { + credentials: 'same-origin' + }) + .then(handleErrors) + .then(function() { + e.closest('article').append(resultMessage('OK!')); + }); + return false; +} + +function getTags() { + fetch('/api/tags?hash=' + document.getElementById('body').getAttribute('data-hash'), { + credentials: 'omit' + }) + .then(handleErrors) + .then(response => { + return response.json(); + }) + .then(json => { + let tags = json.map(t => t.tag); + let input = document.getElementById('tags_input'); + }); + return false; +} + +function addTag(tag) { + document.forms['postmsg'].body.value = '*' + tag + ' ' + document.forms['postmsg'].body.value; + return false; +} + +var users = {}; + +function fetchUserUri(dataUri, callback) { + if (users[dataUri]) { + callback(users[dataUri]); + } else { + let data = new FormData(); + data.append('uri', dataUri); + fetch('/u/', { + method: 'POST', + body: data + }).then(handleErrors) + .then(response => { + return response.json(); + }) + .then(json => { + users[dataUri] = json; + callback(json); + }); + } +} + +/******************************************************************************/ + +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', ''); + 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(); + } + }); + }); + postmsg.addEventListener('submit', e => { + let formData = new FormData(postmsg); + fetch('/api/post' + '?hash=' + document.getElementById('body').getAttribute('data-hash'), { + method: 'POST', + body: formData, + credentials: 'omit' + }).then(handleErrors) + .then(response => { + if (response.ok) { + response.json().then(result => { + if (result.newMessage) { + window.location = new URL(`/m/${result.newMessage.mid}`, window.location.href); + } else { + alert(result.text); + } + }); + } else { + alert('Something went wrong :('); + } + }).catch(error => { + alert(error.message); + }); + e.preventDefault(); + }); + } + document.querySelectorAll('.pmmsg').forEach(pmmsg => { + pmmsg.addEventListener('submit', e => { + let formData = new FormData(pmmsg); + fetch('/api/pm' + '?hash=' + document.getElementById('body').getAttribute('data-hash'), { + method: 'POST', + body: formData, + credentials: 'omit' + }).then(handleErrors) + .then(response => { + if (response.ok) { + response.json().then(result => { + if (result.to) { + window.location = new URL('/pm/sent', window.location.href); + } else { + alert('Something went wrong :('); + } + }); + } else { + alert('Something went wrong :('); + } + }).catch(error => { + alert(error.message); + }); + 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('.l .a-sub').forEach(function(e) { + e.addEventListener('click', function(e) { + subscribeMessage( + e.target, + document.getElementById('content').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'); + } + }); + document.querySelectorAll('[data-uri]').forEach(el => { + let dataUri = el.getAttribute('data-uri'); + if (dataUri) { + setTimeout(() => fetchUserUri(dataUri, user => { + let header = el.closest('.msg-header'); + header.querySelectorAll('.a-username').forEach(a => { + a.setAttribute('href', user.uri); + let img = a.querySelector('img'); + if (img && user.avatar) { + img.setAttribute('src', user.avatar); + img.setAttribute('alt', user.uname); + } + let textNode = a.childNodes[0]; + if (textNode.nodeType === Node.TEXT_NODE && textNode.nodeValue.trim().length > 0) { + let uname = document.createTextNode(user.uname); + a.replaceChild(uname, a.firstChild); + } + }); + }), 100); + } + }); + document.querySelectorAll('[data-user-uri]').forEach(el => { + let dataUri = el.getAttribute('href'); + if (dataUri) { + setTimeout(() => fetchUserUri(dataUri, user => { + let textNode = el.childNodes[0]; + if (textNode.nodeType === Node.TEXT_NODE && textNode.nodeValue.trim().length > 0) { + let uname = document.createTextNode(`@${user.uname}`); + el.replaceChild(uname, el.firstChild); + } + }), 100); + } + }); + initES(); + + 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; + })); + } +}); -- cgit v1.2.3