In daily development, we all have some commonly used code snippets. They can be directly copied and used in various projects, which is very convenient. If you've taken over someone else's project, you may notice some identical utility-class methods across projects. These are the commonly used code snippets of previous developers.

Now, the front-end community is well-developed. There are many great libraries like lodash, dayjs, etc., which can meet our needs for handling arrays, dates, etc. This article won't repeat those common snippets.

1. Detect Clicks Outside an Element

When hiding pop-ups or collapsing dropdowns, use the contains method instead of layer-by-layer checking.

<div id="ele">Content</div>
<script>
const ele = document.getElementById("ele");
document.addEventListener("click", function (evt) {
const isClickedOutside = !ele.contains(evt.target);
if (isClickedOutside) {
console.log("Clicked outside!");
}
});
</script>

2. Quickly Open the Official Website

To view a third-party library's homepage or code repository, use these npm commands:

# Open the homepage
npm home PACKAGE_NAME
# E.g., for React
npm home react
# Open the code repository
npm repo PACKAGE_NAME
# E.g., for React
npm repo react

3. One-Time Event Listener

Besides removing the listener in the event function, you can use the once parameter.

<button id="btn">Click</button>
<script>
const handler = function () {
console.log("Clicked once!");
};
const btn = document.getElementById("btn");
btn.addEventListener("click", handler, { once: true });
</script>

4. Format Seconds into HH:mm:ss

For scenarios like showing audio/video duration, format seconds like this:

const formatSeconds = (s) =>
[parseInt(s / 60 / 60), parseInt((s / 60) % 60), parseInt(s % 60)].join(":").replace(/\b(\d)\b/g, "0$1");
const seconds = 3661;
console.log(formatSeconds(seconds));

To show relative time like "Just now", try the timeago.js library.

5. Convert URL Parameters to an Object

Instead of using the query-string library, use the URLSearchParams API.

const getUrlParams = (query) =>
Array.from(new URLSearchParams(query)).reduce(
(p, [k, v]) => Object.assign({}, p, { [k]: p[k] ? (Array.isArray(p[k]) ? p[k] : [p[k]]).concat(v) : v }),
{}
);
const query = "?a=1&b=2&a=3";
console.log(getUrlParams(query));

6. Open a New Tab

When opening an external link, set rel="noopener noreferrer" to avoid security risks.

<a href="https://example.com" target="_blank" rel="noopener noreferrer">Open</a>
<script>
function openNewTab() {
window.open("https://example.com", "newTab", "noopener,noreferrer");
}
</script>
<button onclick="openNewTab()">Open with window.open</button>

7. Display Uploaded Images

Use the FileReader API's readAsDataURL method to show uploaded images.

<input type="file" id="uploaded-file" />
<div id="result"></div>
<script>
function readImage() {
const fileReader = new FileReader();
const file = document.getElementById("uploaded-file").files[0];
if (file) {
fileReader.readAsDataURL(file);
}
fileReader.addEventListener(
"load",
() => {
const img = document.createElement("img");
img.src = fileReader.result;
document.getElementById("result").append(img);
},
{ once: true }
);
}
document.getElementById("uploaded-file").addEventListener("change", readImage);
</script>

8. File Download

Using the <a> tag's download attribute can trigger a download, but it has limitations.

<a href="/path/to/file" download>Download</a>
<script>
function download(url) {
const link = document.createElement("a");
link.download = "file name";
link.href = url;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
</script>
<button onclick="download('https://example.com/file')">Download with JS</button>

You can also set the response header on the server or use Blob and createObjectURL in the browser.

const data = JSON.stringify({ message: "Hello" });
const blob = new Blob([data], { type: "application/json" });
const url = window.URL.createObjectURL(blob);
download(url);
window.URL.revokeObjectURL(url);

9. Cache Results

Cache function results for complex calculations.

const memoize = (fn) =>
(
(cache = Object.create(null)) =>
(arg) =>
cache[arg] || (cache[arg] = fn(arg))
)();
const complexCalculation = (num) => {
let sum = 0;
for (let i = 1; i <= num; i++) {
sum += i;
}
return sum;
};
const memoizedCalculation = memoize(complexCalculation);
console.log(memoizedCalculation(10));
console.log(memoizedCalculation(10));

10. Multi-Line Ellipsis

Use CSS to truncate text with ellipses for single or multi-line.

.truncate-single {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.truncate-multi {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
<div class="truncate-single">Long single-line text...</div>
<div class="truncate-multi">Long multi-line text... Long multi-line text...</div>

11. Select the Last Few Elements

Use CSS selectors to target specific elements.

li:nth-child(-n + 3) {
text-decoration: underline;
}
li:nth-child(n + 2):nth-child(-n + 5) {
color: #2563eb;
}
li:nth-last-child(-n + 2) {
text-decoration-line: line-through;
}
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>

12. Scrollbar Styles

Customize scrollbar styles with CSS or a third-party library like better-scroll.

::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
border-radius: 10px;
background-color: #fafafa;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: rgb(191, 191, 191);
}
body {
scrollbar-width: thin;
scrollbar-color: #718096 #edf2f7;
}

13. Percentage Calculation-Largest Remainder Method

Use the largest remainder method to ensure percentage sums equal 1.

function getPercentWithPrecision(valueList, precision) {
const digits = Math.pow(10, precision);
const sum = valueList.reduce((total, cur) => total + cur, 0);
const votesPerQuota = valueList.map((val) => (val / sum) * 100 * digits);
const seats = votesPerQuota.map((val) => Math.floor(val));
const remainder = votesPerQuota.map((val) => val - Math.floor(val));
const totalSeats = 100 * digits;
let currentSeats = votesPerQuota.reduce((total, cur) => total + Math.floor(cur), 0);
while (totalSeats - currentSeats > 0) {
let maxIdx = -1;
let maxValue = Number.NEGATIVE_INFINITY;
for (var i = 0; i < remainder.length; i++) {
if (maxValue < remainder[i]) {
maxValue = remainder[i];
maxIdx = i;
}
}
seats[maxIdx]++;
remainder[maxIdx] = 0;
currentSeats++;
}
return seats.map((val) => `${(val / totalSeats) * 100}%`);
}
const values = [56, 12, 48, 56];
console.log(getPercentWithPrecision(values, 2));

14. Limit Concurrency

Limit the number of concurrent requests when making many requests.

async function asyncPool(poolLimit, iterable, iteratorFn) {
const ret = [];
const executing = new Set();
for (const item of iterable) {
const p = Promise.resolve().then(() => iteratorFn(item, iterable));
ret.push(p);
executing.add(p);
const clean = () => executing.delete(p);
p.then(clean).catch(clean);
if (executing.size >= poolLimit) {
await Promise.race(executing);
}
}
return Promise.all(ret);
}
const timeout = (i) => new Promise((resolve) => setTimeout(() => resolve(i), i));
asyncPool(2, [1000, 5000, 3000, 2000], timeout).then((results) => {
console.log(results);
});

15. UUID Generation

Generate unique identifiers with this code.

const uuid = (a) =>
a
? (a ^ ((Math.random() * 16) >> (a / 4))).toString(16)
: ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, uuid);
console.log(uuid());

16. Open Modal and Prevent Body Scroll

Prevent the body from scrolling when opening a modal.

<button onclick="openModal()">Open Modal</button>
<div id="modal" style="display: none;">Modal Content</div>
<script>
function openModal() {
document.body.style.overflow = "hidden";
document.getElementById("modal").style.display = "block";
}
function closeModal() {
document.body.style.removeProperty("overflow");
document.getElementById("modal").style.display = "none";
}
</script>