Skip to content

Instantly share code, notes, and snippets.

View andreasvirkus's full-sized avatar
🙊
made you look

andreas andreasvirkus

🙊
made you look
View GitHub Profile
function resizeImage(el, width, height, quality) {
var canvas = document.createElement('canvas')
canvas.width = width
canvas.height = height
var context = canvas.getContext('2d')
context.drawImage(el, 0, 0, width, height)
try {
return canvas.toDataURL('image/jpeg', quality)
} catch (e) {
@andreasvirkus
andreasvirkus / Modal.vue
Last active September 10, 2022 22:03
Simple Vue modal component
<template>
<transition-fade :duration="200">
<div
v-if="show"
:class="$style.backdrop"
@click="$emit('close')"
@keydown.stop
@keyup.esc="handleEscape"
>
<dialog v-show="show" ref="dialog" :open="show" :class="$style.modal" tabindex="-1">
const roundingStops = [5, 10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000]
export const roundToScale = (count, scale = roundingStops) => {
if (count === 0) return 0
const nearestIdx = scale.findIndex((s) => s > count)
let nearest = scale[nearestIdx]
if (nearestIdx !== 0 && nearest / 2 > count) nearest = scale[nearestIdx - 1] || scale[0]
return nearest || count
export const strip = (html: string) => {
const doc = new DOMParser().parseFromString(html, 'text/html')
return (doc.body.textContent || '').trim()
}
@andreasvirkus
andreasvirkus / Editor.vue
Last active January 20, 2022 15:58
Tiptap emoji plugin for Klausapp
<template>
<div ref="editor" class="notranslate">
<div v-show="showSuggestions" ref="suggestions">
<template v-if="(filteredSuggestions || []).length">
<div
v-for="(item, index) in filteredSuggestions.slice(0, 10)"
:key="index"
:class="[$style.suggestion, navigatedSuggestionIndex === index && $style.selected]"
@click="selectSuggestion(item)"
>
@andreasvirkus
andreasvirkus / debounce.js
Created June 12, 2021 17:12
A modern twist to an oldie, but goldie.
export function debounce(func, timeout = 300){
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => { func.apply(this, args); }, timeout);
};
}
export function stringToHtml(html: string): ChildNode {
var template = document.createElement('template')
html = html.trim() // Never return a text node of whitespace as the result
template.innerHTML = html
return template.content.firstChild
}
// usage:
const div = stringToHtml('<div><span>nested</span> <span>stuff</span></div>')
@andreasvirkus
andreasvirkus / style.css
Last active March 25, 2021 10:04
Vanilla JS Toast component
.toaster {
display: block;
position: fixed;
left: 50%;
transform: translateX(-50%);
bottom: 16px;
width: 100%;
height: 0;
z-index: 11;
}
import Vue from "vue";
function setupWatchers(data = []) {
if (!(this instanceof Vue)) throw new Error("Persistence plugin needs to be called from a Vue component");
if (!data) return;
const query = new URLSearchParams(location.search);
data.forEach((name) => {
const key = `${this.$options.name}_${name}`;
if (query.has(key)) this[name] = JSON.parse(query.get(key));
function buildReport() {
const ss = SpreadsheetApp.getActive();
const data = ss.getSheetByName('SUMMARY').getRange("A1").getValues();
const payload = buildAlert(data);
Logger.log(data);
sendAlert(payload);
}
function buildAlert(data) {
const mrr = data[0][0];