Skip to content

Instantly share code, notes, and snippets.

@Ryu1845
Created November 2, 2022 22:10
Show Gist options
  • Save Ryu1845/7a1cbf39d10cdf9feecda3e96c857e00 to your computer and use it in GitHub Desktop.
Save Ryu1845/7a1cbf39d10cdf9feecda3e96c857e00 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>SNScrape Viewer</title>
<script src="https://unpkg.com/mustache@latest"></script>
<script src="https://cdn.tailwindcss.com"></script>
<script>
function checkVisible(elm, threshold, mode) {
threshold = threshold || 0;
mode = mode || 'visible';
var rect = elm.getBoundingClientRect();
var viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
var above = rect.bottom - threshold < 0;
var below = rect.top - viewHeight + threshold >= 0;
return mode === 'above' ? above : (mode === 'below' ? below : !above && !below);
}
function insertAfter(newNode, existingNode) {
existingNode.parentNode.insertBefore(newNode, existingNode.nextSibling);
}
async function loadTweets() {
const [file] = document.querySelector('input[type=file]').files;
var lines;
if (file) {
var text = await file.text();
lines = text.split(/\r\n|\n/);
}
return new Promise((resolve) => {resolve(lines)});
}
function makeTweetArray(lines, prevRange, currRange) {
var template = document.getElementById('template').innerHTML;
var oldDiv;
var newDiv;
var tweets = [];
for(var line = prevRange; line < lines.length-1 && line < currRange; line++){
newDiv = document.createElement("div");
newDiv.id = line;
var rendered = Mustache.render(template, JSON.parse(lines[line]));
newDiv.innerHTML = rendered;
tweets.push(newDiv);
}
return tweets;
}
async function mainFunc() {
var target = document.getElementById('target');
var container = document.createElement("div");
container.id = "container";
document.body.insertBefore(container, target);
let lines = await loadTweets();
const paginationNumbers = document.getElementById("pagination-numbers");
const nextButton = document.getElementById("next-button");
const prevButton = document.getElementById("prev-button");
const pageNumber = document.getElementById("page-number");
const paginationLimit = 5;
const pageCount = Math.ceil(lines.length / paginationLimit) - 1;
pageNumber.max = pageCount;
let currentPage = 1;
const disableButton = (button) => {
button.classList.add("disabled");
button.setAttribute("disabled", true);
};
const enableButton = (button) => {
button.classList.remove("disabled");
button.removeAttribute("disabled");
};
const handlePageButtonsStatus = () => {
if (currentPage === 1) {
disableButton(prevButton);
} else {
enableButton(prevButton);
}
if (pageCount === currentPage) {
disableButton(nextButton);
} else {
enableButton(nextButton);
}
};
const handleActivePageNumber = () => {
document.querySelectorAll(".pagination-number").forEach((button) => {
button.classList.remove("active");
const pageIndex = Number(button.getAttribute("page-index"));
if (pageIndex == currentPage) {
button.classList.add("active");
}
});
};
const getPageNumber = (index) => {
const pageNumber = document.createElement("button");
pageNumber.className = "pagination-number";
pageNumber.innerHTML = index;
pageNumber.setAttribute("page-index", index);
pageNumber.setAttribute("aria-label", "Page " + index);
return pageNumber;
};
const getPaginationNumbers = () => {
console.log(pageNumber);
let one = getPageNumber(1);
paginationNumbers.insertBefore(one, pageNumber)
let last = getPageNumber(pageCount);
insertAfter(last, pageNumber);
};
const setCurrentPage = (pageNum) => {
container.innerHTML = '';
currentPage = pageNum;
handleActivePageNumber();
handlePageButtonsStatus();
const prevRange = (pageNum - 1) * paginationLimit;
const currRange = pageNum * paginationLimit;
let tweets = makeTweetArray(lines, prevRange, currRange);
target = document.getElementById('target');
tweets.forEach((tweet) => {container.append(tweet)});
};
getPaginationNumbers();
setCurrentPage(1);
pageNumber.oninput = () => {
console.log(document.getElementById("page-number").value);
setCurrentPage(document.getElementById("page-number").value);
}
prevButton.addEventListener("click", () => {
setCurrentPage(currentPage - 1);
});
nextButton.addEventListener("click", () => {
setCurrentPage(currentPage + 1);
});
document.querySelectorAll(".pagination-number").forEach((button) => {
const pageIndex = Number(button.getAttribute("page-index"));
if (pageIndex) {
button.addEventListener("click", () => {
setCurrentPage(pageIndex);
});
}
});
}
</script>
<style type="text/css" media="screen">
.pagination-container {
width: calc(100% - 2rem);
display: flex;
align-items: center;
position: absolute;
bottom: 0;
padding: 1rem 0;
justify-content: center;
}
.pagination-number,
.pagination-button{
font-size: 1.1rem;
background-color: transparent;
border: none;
margin: 0.25rem 0.25rem;
cursor: pointer;
height: 2.5rem;
width: 2.5rem;
border-radius: .2rem;
}
.pagination-number:hover,
.pagination-button:not(.disabled):hover {
background: #fff;
}
.pagination-number.active {
color: #fff;
background: #0085b6;
}
</style>
</head>
<body>
<script id="template" type="x-tmpl-mustache">
<!-- component -->
<div class="font-sans rounded border px-6 py-4 max-w-md">
<div class="flex items-center">
<img src="{{user.profileImageUrl}}" class="h-12 w-12 rounded-full" />
<div class="flex flex-col ml-4">
<a class="font-bold text-black" href="#">{{user.username}}</a>
<span class="text-grey">@{{user.username}}</span>
</div>
<svg viewBox="328 355 335 276" class="ml-auto" height="24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d=" M 630, 425 A 195, 195 0 0 1 331, 600 A 142, 142 0 0 0 428, 570 A 70, 70 0 0 1 370, 523 A 70, 70 0 0 0 401, 521 A 70, 70 0 0 1 344, 455 A 70, 70 0 0 0 372, 460 A 70, 70 0 0 1 354, 370 A 195, 195 0 0 0 495, 442 A 67, 67 0 0 1 611, 380 A 117, 117 0 0 0 654, 363 A 65, 65 0 0 1 623, 401 A 117, 117 0 0 0 662, 390 A 65, 65 0 0 1 630, 425 Z" style="fill:#3BA9EE;"/>
</svg>
</div>
<div class=" mt-3 mb-1 leading-normal text-lg">{{renderedContent}}</div>
<div class="text-grey mb-3 text-sm"></div>
<div class="flex text-grey">
<div class="flex items-center mr-4">
<svg class="mr-2" width="24" height="24" viewBox="0 0 24 24"><path class="fill-current" d="M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.045.286.12.403.143.225.385.347.633.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.368-3.43-7.788-7.8-7.79zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.334-.75-.75-.75h-.395c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z"/></svg>
<span>{{replyCount}}</span>
</div>
<div class="flex items-center mr-4">
<svg class="mr-2" width="24" height="24" viewBox="0 0 24 24"><path class="fill-current" d="M23.77 15.67c-.292-.293-.767-.293-1.06 0l-2.22 2.22V7.65c0-2.068-1.683-3.75-3.75-3.75h-5.85c-.414 0-.75.336-.75.75s.336.75.75.75h5.85c1.24 0 2.25 1.01 2.25 2.25v10.24l-2.22-2.22c-.293-.293-.768-.293-1.06 0s-.294.768 0 1.06l3.5 3.5c.145.147.337.22.53.22s.383-.072.53-.22l3.5-3.5c.294-.292.294-.767 0-1.06zm-10.66 3.28H7.26c-1.24 0-2.25-1.01-2.25-2.25V6.46l2.22 2.22c.148.147.34.22.532.22s.384-.073.53-.22c.293-.293.293-.768 0-1.06l-3.5-3.5c-.293-.294-.768-.294-1.06 0l-3.5 3.5c-.294.292-.294.767 0 1.06s.767.293 1.06 0l2.22-2.22V16.7c0 2.068 1.683 3.75 3.75 3.75h5.85c.414 0 .75-.336.75-.75s-.337-.75-.75-.75z"/></svg>
<span>{{retweetCount}}</span>
</div>
<div class="flex items-center">
<svg class="mr-2" width="24" height="24" viewBox="0 0 24 24"><path class="fill-current" d="M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.813-1.148 2.353-2.73 4.644-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.375-7.454 13.11-10.037 13.156H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.035 11.596 8.55 11.658 1.52-.062 8.55-5.917 8.55-11.658 0-2.267-1.822-4.255-3.902-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.015-.03-1.426-2.965-3.955-2.965z"/></svg>
<span>{{likeCount}}</span>
</div>
</div>
</div>
</script>
<div>
<input type="file" onchange="mainFunc()" id="choose-file" name="choose-file" />
</div>
<div id="target"></div>
<nav class="pagination-container">
<button class="pagination-button" id="prev-button" aria-label="Previous page" title="Previous page">
&lt;
</button>
<div id="pagination-numbers">
<input type="number" id="page-number" name="page-number" min=1>
</div>
<button class="pagination-button" id="next-button" aria-label="Next page" title="Next page">
&gt;
</button>
</nav>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment