diff --git a/library.js b/library.js index df2a1846..3db3ba95 100644 --- a/library.js +++ b/library.js @@ -110,11 +110,13 @@ var content = req.body.content, tid = req.body.tid, url = req.body.url, + toPid = req.body.toPid, uid = req.user ? req.user.uid : 0; topics.reply({ tid: tid, uid: uid, + toPid: toPid, content: content }, function(err, postData) { if(err) { diff --git a/package.json b/package.json index b7148e78..a81da62f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nodebb-plugin-blog-comments", - "version": "0.4.6", + "version": "0.4.7", "description": "NodeBB Blog Comments (Ghost / WP Commenting Engine)", "main": "library.js", "scripts": { diff --git a/public/css/comments.css b/public/css/comments.css index 45ff9a3c..9f7b10c3 100644 --- a/public/css/comments.css +++ b/public/css/comments.css @@ -25,6 +25,7 @@ color: #333; min-height: 75px; position: relative; + transition: background-color 0.6s ease; } #nodebb .topic-body { @@ -89,7 +90,7 @@ #nodebb > ul { margin-bottom: 0px; - margin-top: 20px; + margin-top: 25px; list-style-type: none; padding: 0px; } @@ -205,4 +206,77 @@ width: 20px; height: 20px; border-radius: 100%; -} \ No newline at end of file +} + +#nodebb .sub-reply-input { + margin-left: 20px; + margin-right: 20px; + margin-bottom: 10px; + padding-bottom: 48px; +} + +#nodebb .no-select { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; +} + +#nodebb .post-tools { + float: right; + text-transform: lowercase; +} + +#nodebb .post-tools a { + padding-right: 10px; + cursor: pointer; + color: #38C071; + text-decoration: none; +} + +#nodebb .reply-label { + padding: 1px 5px; + margin: 0; + font-size: 12px; + line-height: 1.5; + color: #333; + background-color: #fff; + cursor: pointer; + border: 1px solid #ccc; + white-space: nowrap; + transition: background-color 0.6s ease; + -webkit-appearance: button; + -moz-appearance: button; +} + +#nodebb .reply-label i { + pointer-events: none; +} + +#nodebb .reply-label:hover { + background-color: #E6E6E6; +} + +#nodebb .hidden { + display: none; +} + +#nodebb-load-more { + transition: background-color 0.6s ease; +} + +#nodebb .highlight { + background-color: rgba(240, 173, 78, 0.75); +} + +#nodebb .btn.btn-primary.highlight { + border-color: rgba(240, 173, 78, 0.75); + background-color: rgba(240, 173, 78, 0.75); +} + +#nodebb .post-content blockquote { + font-size: 12px; + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} diff --git a/public/lib/general.js b/public/lib/general.js index 13f3b050..37f71bee 100644 --- a/public/lib/general.js +++ b/public/lib/general.js @@ -61,11 +61,24 @@ data.pagination = pagination; data.postCount = parseInt(data.postCount, 10); - for (var post in data.posts) { - if (data.posts.hasOwnProperty(post)) { - data.posts[post].timestamp = timeAgo(parseInt(data.posts[post].timestamp), 10); - if (data.posts[post]['blog-comments:url']) { - delete data.posts[post]; + for (var p in data.posts) { + if (data.posts.hasOwnProperty(p)) { + var post = data.posts[p]; + post.timestamp = timeAgo(parseInt(post.timestamp), 10); + post.isReply = post.hasOwnProperty('toPid') && parseInt(post.toPid) !== parseInt(data.tid) - 1; + post.deletedReply = false; + post.parentUsername = ''; + + if (post.hasOwnProperty('parent')) { + if (post.parent.hasOwnProperty('username')) { + post.parentUsername = post.parent.username; + } else { + post.deletedReply = true; + } + } + + if (post['blog-comments:url']) { + delete data.posts[p]; } } } @@ -144,6 +157,71 @@ authenticate('login'); } } + + var nodebbCommentsList = nodebbDiv.querySelector('#nodebb-comments-list'); + var bindOnClick = function(nodeList, handler) { + for (var i = nodeList.length - 1; i >= 0; i--) { + nodeList[i].onclick = handler; + } + }; + var isInViewport = function(element) { + var rect = element.getBoundingClientRect(); + return ( + rect.top >= 0 && rect.left >= 0 && + rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && + rect.right <= (window.innerWidth || document.documentElement.clientWidth) + ); + }; + + bindOnClick(nodebbCommentsList.querySelectorAll('[component="post/parent"]'), function(event) { + var element = event.target; + var goTo = nodebbCommentsList.querySelector('.topic-item[data-pid="' + element.getAttribute('data-topid') + '"]'); + + if (!goTo) { + goTo = nodebbDiv.querySelector('#nodebb-load-more'); + } + + if (!isInViewport(goTo)) { + goTo.scrollIntoView(false); + } + + goTo.classList.add('highlight'); + element.classList.add('highlight'); + + setTimeout(function() { + goTo.classList.remove('highlight'); + element.classList.remove('highlight'); + }, 1000); + + }); + + bindOnClick(nodebbCommentsList.querySelectorAll('[component="post/reply"],[component="post/quote"]'), function(event) { + var topicItem = event.target; + while (topicItem && !topicItem.classList.contains('topic-item')) { + topicItem = topicItem.parentElement; + } + + if (topicItem) { + var elementForm = topicItem.querySelector('form'); + var visibleForm = nodebbCommentsList.querySelector('li .topic-item form:not(.hidden)'); + var formInput = elementForm.querySelector('textarea'); + + if (visibleForm && visibleForm !== elementForm) { + visibleForm.classList.add('hidden'); + } + + if (/\/quote$/.test(event.target.getAttribute('component'))) { + var postBody = topicItem.querySelector('.post-content .post-body'); + var quote = (postBody.innerText ? postBody.innerText : postBody.textContent).split('\n').map(function(line) { return line ? '> ' + line : line; }).join('\n'); + formInput.value = '@' + topicItem.getAttribute('data-userslug') + ' said:\n' + quote + formInput.value; + } else { + formInput.value = '@' + topicItem.getAttribute('data-userslug') + ': ' + formInput.value + } + + elementForm.classList.remove('hidden'); + } + }); + } else { if (data.isAdmin) { if (articleData) { diff --git a/public/lib/ghost.js b/public/lib/ghost.js index 8ab7df1a..0178cce9 100644 --- a/public/lib/ghost.js +++ b/public/lib/ghost.js @@ -61,11 +61,24 @@ data.pagination = pagination; data.postCount = parseInt(data.postCount, 10); - for (var post in data.posts) { - if (data.posts.hasOwnProperty(post)) { - data.posts[post].timestamp = timeAgo(parseInt(data.posts[post].timestamp), 10); - if (data.posts[post]['blog-comments:url']) { - delete data.posts[post]; + for (var p in data.posts) { + if (data.posts.hasOwnProperty(p)) { + var post = data.posts[p]; + post.timestamp = timeAgo(parseInt(post.timestamp), 10); + post.isReply = post.hasOwnProperty('toPid') && parseInt(post.toPid) !== parseInt(data.tid) - 1; + post.deletedReply = false; + post.parentUsername = ''; + + if (post.hasOwnProperty('parent')) { + if (post.parent.hasOwnProperty('username')) { + post.parentUsername = post.parent.username; + } else { + post.deletedReply = true; + } + } + + if (post['blog-comments:url']) { + delete data.posts[p]; } } } @@ -143,6 +156,71 @@ authenticate('login'); } } + + var nodebbCommentsList = nodebbDiv.querySelector('#nodebb-comments-list'); + var bindOnClick = function(nodeList, handler) { + for (var i = nodeList.length - 1; i >= 0; i--) { + nodeList[i].onclick = handler; + } + }; + var isInViewport = function(element) { + var rect = element.getBoundingClientRect(); + return ( + rect.top >= 0 && rect.left >= 0 && + rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && + rect.right <= (window.innerWidth || document.documentElement.clientWidth) + ); + }; + + bindOnClick(nodebbCommentsList.querySelectorAll('[component="post/parent"]'), function(event) { + var element = event.target; + var goTo = nodebbCommentsList.querySelector('.topic-item[data-pid="' + element.getAttribute('data-topid') + '"]'); + + if (!goTo) { + goTo = nodebbDiv.querySelector('#nodebb-load-more'); + } + + if (!isInViewport(goTo)) { + goTo.scrollIntoView(false); + } + + goTo.classList.add('highlight'); + element.classList.add('highlight'); + + setTimeout(function() { + goTo.classList.remove('highlight'); + element.classList.remove('highlight'); + }, 1000); + + }); + + bindOnClick(nodebbCommentsList.querySelectorAll('[component="post/reply"],[component="post/quote"]'), function(event) { + var topicItem = event.target; + while (topicItem && !topicItem.classList.contains('topic-item')) { + topicItem = topicItem.parentElement; + } + + if (topicItem) { + var elementForm = topicItem.querySelector('form'); + var visibleForm = nodebbCommentsList.querySelector('li .topic-item form:not(.hidden)'); + var formInput = elementForm.querySelector('textarea'); + + if (visibleForm && visibleForm !== elementForm) { + visibleForm.classList.add('hidden'); + } + + if (/\/quote$/.test(event.target.getAttribute('component'))) { + var postBody = topicItem.querySelector('.post-content .post-body'); + var quote = (postBody.innerText ? postBody.innerText : postBody.textContent).split('\n').map(function(line) { return line ? '> ' + line : line; }).join('\n'); + formInput.value = '@' + topicItem.getAttribute('data-userslug') + ' said:\n' + quote + formInput.value; + } else { + formInput.value = '@' + topicItem.getAttribute('data-userslug') + ': ' + formInput.value + } + + elementForm.classList.remove('hidden'); + } + }); + } else { if (data.isAdmin) { var markdown = document.getElementById('nbb-markdown').innerHTML diff --git a/public/lib/wordpress.js b/public/lib/wordpress.js index b1554a46..d83eedcb 100644 --- a/public/lib/wordpress.js +++ b/public/lib/wordpress.js @@ -61,11 +61,24 @@ data.pagination = pagination; data.postCount = parseInt(data.postCount, 10); - for (var post in data.posts) { - if (data.posts.hasOwnProperty(post)) { - data.posts[post].timestamp = timeAgo(parseInt(data.posts[post].timestamp), 10); - if (data.posts[post]['blog-comments:url']) { - delete data.posts[post]; + for (var p in data.posts) { + if (data.posts.hasOwnProperty(p)) { + var post = data.posts[p]; + post.timestamp = timeAgo(parseInt(post.timestamp), 10); + post.isReply = post.hasOwnProperty('toPid') && parseInt(post.toPid) !== parseInt(data.tid) - 1; + post.deletedReply = false; + post.parentUsername = ''; + + if (post.hasOwnProperty('parent')) { + if (post.parent.hasOwnProperty('username')) { + post.parentUsername = post.parent.username; + } else { + post.deletedReply = true; + } + } + + if (post['blog-comments:url']) { + delete data.posts[p]; } } } @@ -144,6 +157,71 @@ authenticate('login'); } } + + var nodebbCommentsList = nodebbDiv.querySelector('#nodebb-comments-list'); + var bindOnClick = function(nodeList, handler) { + for (var i = nodeList.length - 1; i >= 0; i--) { + nodeList[i].onclick = handler; + } + }; + var isInViewport = function(element) { + var rect = element.getBoundingClientRect(); + return ( + rect.top >= 0 && rect.left >= 0 && + rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && + rect.right <= (window.innerWidth || document.documentElement.clientWidth) + ); + }; + + bindOnClick(nodebbCommentsList.querySelectorAll('[component="post/parent"]'), function(event) { + var element = event.target; + var goTo = nodebbCommentsList.querySelector('.topic-item[data-pid="' + element.getAttribute('data-topid') + '"]'); + + if (!goTo) { + goTo = nodebbDiv.querySelector('#nodebb-load-more'); + } + + if (!isInViewport(goTo)) { + goTo.scrollIntoView(false); + } + + goTo.classList.add('highlight'); + element.classList.add('highlight'); + + setTimeout(function() { + goTo.classList.remove('highlight'); + element.classList.remove('highlight'); + }, 1000); + + }); + + bindOnClick(nodebbCommentsList.querySelectorAll('[component="post/reply"],[component="post/quote"]'), function(event) { + var topicItem = event.target; + while (topicItem && !topicItem.classList.contains('topic-item')) { + topicItem = topicItem.parentElement; + } + + if (topicItem) { + var elementForm = topicItem.querySelector('form'); + var visibleForm = nodebbCommentsList.querySelector('li .topic-item form:not(.hidden)'); + var formInput = elementForm.querySelector('textarea'); + + if (visibleForm && visibleForm !== elementForm) { + visibleForm.classList.add('hidden'); + } + + if (/\/quote$/.test(event.target.getAttribute('component'))) { + var postBody = topicItem.querySelector('.post-content .post-body'); + var quote = (postBody.innerText ? postBody.innerText : postBody.textContent).split('\n').map(function(line) { return line ? '> ' + line : line; }).join('\n'); + formInput.value = '@' + topicItem.getAttribute('data-userslug') + ' said:\n' + quote + formInput.value; + } else { + formInput.value = '@' + topicItem.getAttribute('data-userslug') + ': ' + formInput.value + } + + elementForm.classList.remove('hidden'); + } + }); + } else { if (data.isAdmin) { var adminXHR = newXHR(); diff --git a/public/templates/comments/comments.tpl b/public/templates/comments/comments.tpl index 75ca202a..932fa1c0 100644 --- a/public/templates/comments/comments.tpl +++ b/public/templates/comments/comments.tpl @@ -27,7 +27,7 @@