<!DOCTYPE html>
<html lang="en">
<head>
<!-- 123213 -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LZ-String Example</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/setImmediate/1.0.5/setImmediate.min.js"></script>
<style>
* {
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
background-color: #f4f4f4;
color: #333;
}
.container {
max-width: 600px;
margin: 20px auto;
padding: 20px;
border: 1px solid #ddd;
background-color: #fff;
box-shadow: 0 4px 8px rgba(0,0,0,0.05);
border-radius: 8px;
}
h1, h2, h3 {
text-align: center;
}
h2, h3 {
text-align: left;
}
textarea, select, button {
width: 100%;
padding: 10px;
margin-bottom: 15px;
border: 1px solid #ccc;
border-radius: 4px;
}
button {
background-color: #0084ff;
color: white;
font-weight: 500;
cursor: pointer;
}
button:hover {
background-color: #0066cc;
}
#toolbar {
--position-default: absolute;
--position-value: var(--position-default);
position: var(--position-value);
display: inline-flex;
flex-direction: row;
flex-wrap: nowrap;
white-space: nowrap;
transform: translate(-100%,-100%);
margin-top: -4px;
gap: 4px;
align-items: center;
}
#toolbar.hide {
--position-value: none;
}
#toolbar:hover {
position: var(--position-default);
}
#toolbar span {
padding: 0 4px;
}
#toolbar button {
margin-right: 5px;
width: 4em;
font-size: 12px;
padding: 4px;
margin: 0;
transition: all 0.1s ease;
}
#toolbar button.clicked {
transform: scale(0.95);
background-color: #184340;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
color: white;
}
#inputText, #compressedInput {
background: #f0f6ff;
}
#compressedText, #decompressedText {
background: #fafafa;
}
@media (max-width: 600px) {
.container {
width: 90%;
margin: 10px auto;
}
h1, h2, h3 {
font-size: 1.2em;
}
}
</style>
</head>
<body>
<div class="container">
<h1>LZ-String Compression Example</h1>
<h2>Compression Method</h2>
<select id="compressionMethod">
<option value="compress">Compress</option>
<option value="compressToUTF16">Compress to UTF16</option>
<option value="compressToBase64">Compress to Base64</option>
<option value="compressToEncodedURIComponent">Compress to Encoded URI Component</option>
<option value="compressToUint8Array">Compress to Uint8Array</option>
</select>
<h2>Compression</h2>
<textarea id="inputText" placeholder="Enter text to compress"></textarea>
<button onclick="compressText()">Compress</button>
<h3>Compressed Text:</h3>
<textarea id="compressedText" readonly></textarea>
<h2>Decompression</h2>
<textarea id="compressedInput" placeholder="Enter compressed text"></textarea>
<button onclick="decompressText()">Decompress</button>
<h3>Decompressed Text:</h3>
<textarea id="decompressedText" readonly></textarea>
</div>
<div id="toolbar">
<span id="textCount"></span>
<button onclick="copyText(this)">Copy</button>
<button onclick="pasteText(this)">Paste</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lz-string/1.5.0/lz-string.min.js"></script>
<script>
// browser safe text for copy & paste
const jzEncode = t => JSON.stringify({"t":t}).slice(6, -2);
const jzDecode = t => JSON.parse(`{"t":"${t}"}`).t;
function compressText() {
const inputText = document.getElementById('inputText').value;
const method = document.getElementById('compressionMethod').value;
let compressedText = '';
try {
switch (method) {
case 'compressToUTF16':
compressedText = LZString.compressToUTF16(inputText);
break;
case 'compressToBase64':
compressedText = LZString.compressToBase64(inputText);
break;
case 'compressToEncodedURIComponent':
compressedText = LZString.compressToEncodedURIComponent(inputText);
break;
case 'compressToUint8Array':
const uint8Array = Array.from(LZString.compressToUint8Array(inputText));
compressedText = uint8Array.map(byte => byte.toString(16).padStart(2, '0').toUpperCase()).join(' ');
break;
default:
compressedText = LZString.compress(inputText);
}
} catch (e) {
compressedText = 'Error during compression: ' + e.message;
}
document.getElementById('compressedText').value = compressedText;
}
function decompressText() {
const compressedInput = document.getElementById('compressedInput').value;
const method = document.getElementById('compressionMethod').value;
let decompressedText = '';
try {
switch (method) {
case 'compressToUTF16':
decompressedText = LZString.decompressFromUTF16(compressedInput);
break;
case 'compressToBase64':
decompressedText = LZString.decompressFromBase64(compressedInput);
break;
case 'compressToEncodedURIComponent':
decompressedText = LZString.decompressFromEncodedURIComponent(compressedInput);
break;
case 'compressToUint8Array':
const bytes = compressedInput.split(' ').map(hex => parseInt(hex, 16));
decompressedText = LZString.decompressFromUint8Array(new Uint8Array(bytes));
break;
default:
decompressedText = LZString.decompress(compressedInput);
}
} catch (e) {
decompressedText = 'Error during decompression: ' + e.message;
}
document.getElementById('decompressedText').value = decompressedText;
}
!('ontouchstart' in document.documentElement) && document.addEventListener('click', function (evt) {
if (evt.target instanceof HTMLTextAreaElement && !(getSelection() + "")) {
evt.target.select();
}
}, true);
document.addEventListener('transitionend', function(evt) {
if (evt.target instanceof HTMLButtonElement) {
evt.target.classList.remove('clicked'); // Remove the 'clicked' class at the end of the transition
}
}, true);
let cid = 0;
const copied = new Set();
async function copyText(btn) {
clearTimeout(cid);
let textarea = document.getElementById('toolbar').currentTextArea;
if (!textarea) return;
btn.classList.add('clicked');
textarea.select();
textarea.setSelectionRange(0, textarea.value.length); // For mobile devices
if (!document.execCommand("copy")) {
await navigator.clipboard.writeText(textarea.value)
};
}
async function pasteText(btn) {
clearTimeout(cid);
let textarea = document.getElementById('toolbar').currentTextArea;
if (!textarea || textarea.readOnly) return;
btn.classList.add('clicked');
textarea.focus();
textarea.select();
textarea.setSelectionRange(0, textarea.value.length); // For mobile devices
let pastedText = !document.execCommand('paste') ? await navigator.clipboard.readText() : null;
if (pastedText) {
if (copied.has(pastedText)) pastedText= jzDecode(pastedText);
let startPos = textarea.selectionStart;
let endPos = textarea.selectionEnd;
// Insert text
textarea.value = textarea.value.substring(0, startPos)
+ pastedText
+ textarea.value.substring(endPos, textarea.value.length);
// Update cursor position
textarea.selectionStart = textarea.selectionEnd = startPos + pastedText.length;
};
textarea.select();
textarea.setSelectionRange(0, textarea.value.length); // For mobile devices
}
function updateTextCount() {
let c = document.getElementById('toolbar') || 0;
let d = c.currentTextArea || 0;
if (!d) return;
document.querySelector('#textCount').textContent = `${d.value.length} chars`;
}
document.addEventListener('input', () => {
updateTextCount();
}, true);
document.addEventListener('focusin', function (e) {
if (e.target.tagName === 'TEXTAREA') {
clearTimeout(cid);
cid = setTimeout(() => {
let toolbar = document.getElementById('toolbar');
toolbar.classList.remove('hide');
let rect = e.target.getBoundingClientRect();
toolbar.style.top = `${rect.top + window.scrollY}px`; // Adjust the position as needed
toolbar.style.left = `${rect.right}px`;
toolbar.currentTextArea = e.target;
updateTextCount();
}, 30)
}
});
document.addEventListener('focusout', function (e) {
if (e.target.tagName === 'TEXTAREA') {
let toolbar = document.getElementById('toolbar');
clearTimeout(cid);
cid = setTimeout(() => {
toolbar.classList.add('hide');
}, 30);
}
});
document.addEventListener("copy", (e) => {
let activeElement = document.activeElement;
const target = e.target;
if (target instanceof HTMLTextAreaElement && target === activeElement) {
let paste = window.getSelection().toString();
if (paste) {
// Save the original value and selection
let originalValue = activeElement.value;
let originalStart = activeElement.selectionStart;
let originalEnd = activeElement.selectionEnd;
// Modify the text to be copied
let modifiedText0 = originalValue.substring(originalStart, originalEnd);
let modifiedText = jzEncode(modifiedText0);
if(modifiedText0 !== modifiedText) copied.add(modifiedText);
// Temporarily change the value and select the modified text
activeElement.value = modifiedText;
activeElement.setSelectionRange(0, modifiedText.length);
// Wait for the browser to copy
setImmediate(()=> {
// Restore the original value and selection
activeElement.value = originalValue;
activeElement.setSelectionRange(originalStart, originalEnd);
});
}
}
});
document.addEventListener("paste", (e) => {
const target = e.target;
if (target instanceof HTMLTextAreaElement && !target.readOnly) {
let paste = (e.clipboardData || window.clipboardData).getData("text");
if (copied.has(paste)) {
const decoded = jzDecode(paste);
e.preventDefault();
if (!document.execCommand("insertText", false, decoded)) {
// Modify the pasted data
let modifiedData = decoded; // jzDecode(paste)
// Insert the modified data into the textarea
let textarea = e.target;
let cursorPos = textarea.selectionStart;
let textBefore = textarea.value.substring(0, cursorPos);
let textAfter = textarea.value.substring(textarea.selectionEnd, textarea.value.length);
// Set the new value and position the cursor
textarea.value = textBefore + modifiedData + textAfter;
textarea.selectionStart = textarea.selectionEnd = cursorPos + modifiedData.length;
}
}
}
});
</script>
</body>
</html>
Could you please add this complete demo to show the usage of
lz-string?Demo Link