codepens/copy-table-as-csv-web-compo.../dist/script.js

142 lines
3.7 KiB
JavaScript

import {
LitElement,
html,
css
} from "https://unpkg.com/lit@2.1.4/index.js?module";
class CopyTable extends LitElement {
static styles = css`
:host {
display: grid;
grid-template-columns: minmax(auto, max-content) max-content;
gap: 0.5rem;
width: 100%;
overflow: hidden;
}
.actions {
display: flex;
flex-direction: column;
justify-content: start;
align-items: start;
gap: 0.5rem;
}
button {
appearance: none;
border: none;
background: transparent;
padding: 0;
}
a {
color: currentColor;
}
.overflow {
max-width: 100%;
overflow-x: auto;
}
`;
static properties = {
_success: { state: false }
};
constructor() {
super();
const trs = this.querySelectorAll("tr");
this.CSV = (function () {
let returnString = [];
trs.forEach((tr) => {
let tds = tr.querySelectorAll("td,th");
let tdContent = [...tds].map((td) =>
td.textContent.match(",") ? `"${td.textContent}"` : td.textContent
);
returnString.push(tdContent.join(","));
});
return returnString.join("\n");
})();
}
copyToClipboard(event) {
var type = "text/plain";
var blob = new Blob([this.CSV], { type });
var data = [new ClipboardItem({ [type]: blob })];
navigator.clipboard.write(data).then(() => {
this._success = true;
setTimeout(() => {
this._success = false;
}, 1000);
});
}
render() {
return html`
<div class="overflow">
<slot></slot>
</div>
<div class="actions">
<button aria-label="Copy as CSV" @click="${this.copyToClipboard}">
${this._success
? html`
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
height="24"
width="24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"
/>
</svg>
`
: html`
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
width="24"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"
/>
</svg>
`}
</button>
<a
aria-label="Download CSV"
download="table.csv"
href="data:,${encodeURIComponent(this.CSV)}"
>
<svg
xmlns="http://www.w3.org/2000/svg"
height="24"
width="24"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
/>
</svg>
</a>
</div>
`;
}
}
customElements.define("copy-table", CopyTable);