View Source
prefab-ui-fun-with-hacker-news-example.js [view raw]
function demoHackernews(runner) {
const { $, _, prefab } = runner;
let allCommentsCount, $commentsWithoutLinks;
prefab.clearReport();
prefab.userSettings.addInput('How many rows of stats would you like to display?', { name: 'maxRows', default: 8, type: 'number' });
prefab.userSettings.addSelect('Modify the page to display highlights?', [ 'yes', 'no' ], { name: 'modifyDom', default: 'yes' });
if (location.host !== 'news.ycombinator.com' || location.pathname !== '/item') {
prefab.reportHtml('<h2>Waiting for HackerNews comments page.</h2><p>Tip: visit <a href="https://news.ycombinator.com/best">Hacker News /best</a></p>');
} else {
runOnDiscussionPage();
}
function runOnDiscussionPage() {
allCommentsCount = $('tr.comtr').length;
$commentsWithoutLinks = $('.comment:visible > span:not(:has(a[rel=nofollow]))').closest('tr.comtr');
prefab.mainMenu.addButton('Toggle Comments Without Links', () => {
$commentsWithoutLinks.toggle();
updateUi();
});
runner.on(prefab.Event.UserSettingsChanged, updateUi);
updateUi();
}
function updateUi() {
prefab.userSettings.snapshot().then(userSettings => {
const stats = _commenterStats(userSettings.maxRows || 8);
const areAllVisible = $('tr.comtr').length === allCommentsCount;
prefab.reportTable(stats, { segmentId: 'commenterStatistics', sortScore: 20 });
prefab.reportHtml('<h2>Commenter Stats</h2>' +
'<p>' + (allCommentsCount - $commentsWithoutLinks.length) + ' of ' + allCommentsCount + ' posts contain external links. ' +
'<strong>' + (areAllVisible ? 'Not hiding' : 'Hiding ' + $commentsWithoutLinks.length) + ' posts.</strong></p>'
, { segmentId: 'myCustomHtmlIntro', sortScore: 10 });
_doSomethingWithTheDom(stats, userSettings.modifyDom === 'no');
});
}
function _commenterStats(maxRows) {
let res = {};
$('a.hnuser:visible').each((i, el) => {
const $el = $(el);
const username = $el.text();
res[username] = res[username] || { name: username, posts: 0, chars: 0 };
res[username].posts += 1;
res[username].chars += $el.closest('td').text().length;
});
return _.orderBy(Object.values(res), [ 'posts', 'chars' ], [ 'desc', 'desc' ]).slice(0, maxRows);
}
function _doSomethingWithTheDom(stats, skipDomModification) {
$('.inserted-posts-count').remove();
if (skipDomModification) {
return;
}
const gemStyle = 'padding: 3px 8px; margin: 0 4px 0 6px; color: #ffcb05; background-color: #00274c; border-radius: 2px;';
stats.forEach((userInfo) => {
const postCount = userInfo.posts;
const userPosts = $(`a[href="user?id=${ userInfo.name }"]`);
$(`<span class="inserted-posts-count" style="${ gemStyle }">${ postCount } comment${ postCount > 1 ? 's' : '' }</span>`)
.click(evt => {
const clickedEl = $(evt.target).prev('a')[0];
const nextEl = userPosts[(_.findIndex(userPosts, (el) => el === clickedEl) + 1) % userPosts.length];
$('body').animate({ scrollTop: $(nextEl).offset().top });
})
.css({ cursor: 'pointer' })
.insertAfter(userPosts);
});
}
}