// ==UserScript== // @name 知乎手机网页版改进 // @namespace https://www.zhihu.com/ // @match https://www.zhihu.com/question/* // @grant none // @version 1.1 // @author nameldk // @description 使手机网页版可以加载更多答案 // @downloadURL none // ==/UserScript== const questionNumber = (location.href.match(/\/question\/(\d+)/)||[])[1]; const inDetailPage = location.href.match(/\/question\/\d+\/answer\/\d+/); const fromMobile = navigator.userAgent.match(/Android|iPhone|iPad|iPod|Opera Mini|IEMobile/i); var offset = 0; var limit = 5; var is_end = 0; var elList = null; var elLoading = null; var loadAnswerInterval = null; var loadCommentInterval = null; var viewportElCheckList = []; function removeIt(s) { Array.prototype.forEach.call(document.querySelectorAll(s), function (ele) { ele.remove(); }); } function skipOpenApp() { // .ContentItem.AnswerItem // .RichContent.is-collapsed.RichContent--unescapable Array.prototype.forEach.call(document.querySelectorAll('.ContentItem.AnswerItem'), function (ele) { ele.classList.add('my-fold'); var elRichContentInner = ele.querySelector('.RichContent-inner'); var button = ele.querySelector('button'); if (button) { button.remove(); } if (elRichContentInner) { elRichContentInner.insertAdjacentHTML('afterend', `↓展开↓↑收起↑`); elRichContentInner.parentElement.classList.remove('is-collapsed'); elRichContentInner.setAttribute("style", ""); processFold(elRichContentInner.parentElement); } ele.addEventListener("click", function (event) { event.preventDefault(); event.stopPropagation(); if (elRichContentInner) { elRichContentInner.setAttribute("style", ""); } }); bindClickComment(ele.parentElement); }); document.body.style.overflow = "auto"; } function removeAds() { Array.prototype.forEach.call(document.querySelectorAll('.MBannerAd'), function (ele) { ele.parentNode.removeChild(ele) }); } function removeBlock() { removeIt('.MobileModal-backdrop'); removeIt('.MobileModal--plain.ConfirmModal'); removeIt('.AdBelowMoreAnswers'); removeIt('div.Card.HotQuestions'); removeIt('button.OpenInAppButton.OpenInApp'); } function formatNumber(num) { if (num > 10000) { return (num / 10000).toFixed(2) + '万'; } else { return num; } } function processContent(content) { if (!content) return ''; var r = //g; return content.replace(r, ''); } function loadContent(offset, limit) { var url = `https://www.zhihu.com/api/v4/questions/${questionNumber}/answers?include=data%5B%2A%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%2Cpaid_info_content%3Bdata%5B%2A%5D.mark_infos%5B%2A%5D.url%3Bdata%5B%2A%5D.author.follower_count%2Cbadge%5B%2A%5D.topics&limit=${limit}&offset=${offset}&platform=desktop&sort_by=default`; return fetch(url).then(response => response.json()); } function buildHtml(data) { var content = processContent(data.content); var html = `
${content}
↓展开↓ ↑收起↑
`; return html; } function getListWrap() { if (!elList) { elList = document.querySelectorAll('.Question-main .List'); if (elList) elList = elList[elList.length - 1]; } return elList; } function loadAnswer() { if (is_end) { return; } if (elLoading) { elLoading.classList.remove('hide'); } loadContent(offset, limit).then(function (data) { if (elLoading) { elLoading.classList.add('hide'); } console.log('get data:', offset, limit); if (data.paging.is_end) { is_end = 1; alert('到底了~'); return; } offset += data.data.length; data.data.forEach(function (item) { let elListItemWrap = document.createElement('div'); elListItemWrap.innerHTML = buildHtml(item); getListWrap().insertAdjacentElement("beforeend", elListItemWrap); processFold(elListItemWrap); bindClickComment(elListItemWrap); }); }) } function isElementInViewport (el) { // https://stackoverflow.com/questions/123999/how-can-i-tell-if-a-dom-element-is-visible-in-the-current-viewport if (!el) return false; var rect = el.getBoundingClientRect(); if (rect.top >= 0) { // ↓ return rect.top < window.innerHeight; } else { return rect.top + rect.height > 0; } } function addViewportCheckList(elListItem) { if (elListItem) { viewportElCheckList.push(elListItem); } } function removeViewportCheckList(elListItem) { viewportElCheckList.forEach(function (v, i) { if (v === elListItem) { viewportElCheckList.splice(i, 1); } }) } function processFold(elRichContent) { var elMoreBtn = elRichContent.querySelector('.my-more-btn'); var elLessBtn = elRichContent.querySelector('.my-less-btn'); var elContentItem = elLessBtn.closest('.ContentItem'); if (elMoreBtn && elLessBtn && elContentItem) { elMoreBtn.addEventListener('click', function (e) { elContentItem.classList.add('my-unfold'); elContentItem.classList.remove('my-fold'); addViewportCheckList(elContentItem); }); elLessBtn.addEventListener('click', function (e) { elContentItem.classList.add('my-fold'); elContentItem.classList.remove('my-unfold'); removeViewportCheckList(elContentItem); }); } } function bindLoadData() { var el = document.querySelector('div.Card.ViewAllInappCard'); if (inDetailPage) { el.style.textAlign = "center"; el.innerHTML = '查看所有问题'; return; } el.insertAdjacentHTML('beforebegin', `
`); elLoading = document.getElementById('my-loading'); window.onscroll = function() { if ((window.innerHeight + window.scrollY + 50) >= document.body.offsetHeight) { console.log('reach bottom'); if (loadAnswerInterval) { clearTimeout(loadAnswerInterval); } loadAnswerInterval = setTimeout(function(){ console.log('to load', offset, limit); loadAnswer(); }, 100); } }; } function bindProcessViewport() { var interval; document.addEventListener('scroll', function () { if (interval) { clearTimeout(interval); } interval = setTimeout(function () { // console.log('scroll-view:', viewportElCheckList.length); if (viewportElCheckList.length) { viewportElCheckList.forEach(function (elListItem) { var elLessBtn = elListItem.querySelector('.my-less-btn'); if (isElementInViewport(elListItem)) { elLessBtn.classList.remove('hide'); } else { elLessBtn.classList.add('hide'); } }); } }, 100); }, false); } function loadCommentData(answerId, offset, isReverse) { if (!answerId) { return; } let url = `https://www.zhihu.com/api/v4/answers/${answerId}/root_comments?limit=10&offset=${offset}&order=normal&status=open`; if (isReverse) url = `https://www.zhihu.com/api/v4/answers/${answerId}/comments?limit=10&offset=${offset}&order=reverse&status=open`; return fetch(url).then(response => response.json()); } function bindClickComment(elListItem) { if (!elListItem) return; let elButton = elListItem.querySelector('button.ContentItem-action.Button--withLabel'); let elComment = elListItem.querySelector('.Comments-container'); elButton.addEventListener('click', function () { if (elComment) { elComment.classList.toggle('hide'); } else { let answerId = (elListItem.querySelector('.ContentItem-meta ~ meta[itemprop="url"]').getAttribute('content').match(/\/answer\/(\d+)/) || [])[1]; elComment = addCommentWrap(elListItem, answerId); let elCommentWrap = elComment.querySelector('.CommentListV2'); let elSwitchBtn = elComment.querySelector('div.Topbar-options > button'); let elCommentFold = elComment.querySelector('a.comment-fold'); elComment.dataset.answerId = answerId; elComment.dataset.offset = 0; processComment(elComment, elCommentWrap); elCommentWrap.addEventListener('scroll', function(){ if (elCommentWrap.scrollTop + elCommentWrap.offsetHeight + 20 > elCommentWrap.scrollHeight) { processComment(elComment, elCommentWrap); } }, false); elSwitchBtn.addEventListener('click', function(){ if (elSwitchBtn.innerText === '切换为时间排序') { elSwitchBtn.innerText = '切换为默认排序'; elComment.dataset.isReverse = 0; } else { elSwitchBtn.innerText = '切换为时间排序'; elComment.dataset.isReverse = 1; } elComment.dataset.offset = 0; elCommentWrap.innerHTML = ''; processComment(elComment, elCommentWrap); }); elCommentFold.addEventListener('click', function(){ elComment.classList.add('hide'); }); } }); } function addCommentWrap(elListItem, answerId) { if (!elListItem) return; var commentCount = elListItem.querySelector('meta[itemprop="commentCount"]').getAttribute('content'); let html = `

${commentCount} 条评论

收起
`; elListItem.insertAdjacentHTML("beforeend", html); return elListItem.querySelector('.Comments-container'); } function genCommentHtml(dataList) { if (!dataList || !dataList.length) return ''; let html = ''; dataList.forEach(function(data) { html += genCommentItem(data, data.child_comment_count, 0); if (data.child_comment_count) { data.child_comments.forEach(function (v) { html += genCommentItem(v, 0, 1); }) } }); if (html) { return ``; } return html; } function formatUrl(url, formatStr) { if (!formatStr) formatStr = 'xs'; // s,xs,m, r return url.replace('{size}', formatStr); } function dateFormat(e, t) { if(e.toString().length === 10) { // 秒 e = e*1000; } e = new Date(e); // yyyy-MM-dd hh:mm:ss var n = { "M+": e.getMonth() + 1, "d+": e.getDate(), "h+": e.getHours(), "m+": e.getMinutes(), "s+": e.getSeconds(), "q+": Math.floor((e.getMonth() + 3) / 3), S: e.getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (e.getFullYear() + "").substr(4 - RegExp.$1.length))); for (var r in n) new RegExp("(" + r + ")").test(t) && (t = t.replace(RegExp.$1, 1 === RegExp.$1.length ? n[r] : ("00" + n[r]).substr(("" + n[r]).length))); return t } function getDate(timestamp) { return dateFormat(timestamp, 'yyyy-MM-dd'); } function genCommentItem(item, hasChild, isChild) { const liClass = !hasChild ? 'rootCommentNoChild' : (isChild ? 'child' : 'rootComment'); var replyHtml = ''; if (item.reply_to_author) { replyHtml = ` (作者) 回复 ${item.reply_to_author.member.name} `; } var html = `
  • ${item.author.member.name} ${item.author.member.name} ${replyHtml} ${getDate(item.created_time)}
    ${item.content}
  • `; return html; } function genCommentLoding() { var html = `
    `; var el = document.createElement('div'); el.innerHTML = html; return el; } function processComment(elComment, elCommentWrap) { if (!elComment || !elCommentWrap) { return; } let offset = +elComment.dataset.offset, answerId = elComment.dataset.answerId, isReverse = +elComment.dataset.isReverse, isEnd = +elComment.dataset.isEnd ; if (loadCommentInterval) { clearTimeout(loadCommentInterval); } if (!answerId || isEnd) { return; } loadCommentInterval = setTimeout(function() { console.log('beginLoadComment', offset); var elLoading = genCommentLoding(); elCommentWrap.appendChild(elLoading); loadCommentData(answerId, offset, isReverse).then(function (json) { console.log('getCommentData', offset); elComment.dataset.offset = offset + 10; elCommentWrap.removeChild(elLoading); elLoading = null; let html = genCommentHtml(json.data); if (json.paging.is_end) { elComment.dataset.isEnd = 1; html += '
    评论全部已加载完成...
    ' } elCommentWrap.insertAdjacentHTML('beforeend', html); }); }, 100); } function addCss() { var style = ` `; document.body.insertAdjacentHTML('beforeend', style); } // init if (fromMobile) { setTimeout(function () { addCss(); skipOpenApp(); removeAds(); removeBlock(); bindLoadData(); bindProcessViewport(); }, 200); setTimeout(function () { offset += document.querySelectorAll('.List-item').length; }, 1000); }