DotSlashGabut commited on
Commit
06628ce
·
verified ·
1 Parent(s): 96f80c7

Add 2 files

Browse files
Files changed (2) hide show
  1. index.html +336 -31
  2. prompts.txt +0 -0
index.html CHANGED
@@ -37,6 +37,38 @@
37
  .copy-btn:active {
38
  transform: scale(0.95);
39
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  </style>
41
  </head>
42
  <body class="bg-gray-100 min-h-screen">
@@ -74,6 +106,7 @@
74
  <label for="method" class="block text-sm font-medium text-gray-700 mb-2">Encoding Method</label>
75
  <select id="method" class="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
76
  <option value="base64">Base64</option>
 
77
  <option value="url">URL Encoding</option>
78
  <option value="html">HTML Entities</option>
79
  <option value="hex">Hexadecimal</option>
@@ -84,7 +117,19 @@
84
 
85
  <div class="mb-6">
86
  <label for="input-text" class="block text-sm font-medium text-gray-700 mb-2">Input Text</label>
87
- <textarea id="input-text" rows="5" class="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Enter text to encode/decode..."></textarea>
 
 
 
 
 
 
 
 
 
 
 
 
88
  </div>
89
 
90
  <div class="flex space-x-4 mb-6">
@@ -92,7 +137,7 @@
92
  <i class="fas fa-cog mr-2"></i> Process
93
  </button>
94
  <button id="clear-btn" class="flex-1 bg-gray-200 hover:bg-gray-300 text-gray-800 py-3 px-6 rounded-lg font-medium transition flex items-center justify-center">
95
- <i class="fas fa-trash-alt mr-2"></i> Clear
96
  </button>
97
  </div>
98
 
@@ -100,15 +145,22 @@
100
  <div class="flex justify-between items-center mb-3">
101
  <h3 class="font-medium text-gray-700">Result</h3>
102
  <div class="flex space-x-2">
103
- <button id="copy-btn" class="copy-btn bg-blue-100 text-blue-600 p-2 rounded-lg hover:bg-blue-200">
 
 
 
 
104
  <i class="fas fa-copy"></i>
 
105
  </button>
106
- <button id="expand-btn" class="copy-btn bg-gray-200 text-gray-600 p-2 rounded-lg hover:bg-gray-300">
107
  <i class="fas fa-expand"></i>
 
108
  </button>
109
  </div>
110
  </div>
111
  <div id="result" class="text-gray-800 whitespace-pre-wrap break-words"></div>
 
112
  </div>
113
  </div>
114
 
@@ -117,15 +169,15 @@
117
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 text-sm text-gray-600">
118
  <div class="bg-white p-3 rounded-lg shadow-sm">
119
  <h4 class="font-medium text-blue-600 mb-1">Base64</h4>
120
- <p>Encodes binary data to ASCII characters. Commonly used for email attachments and embedding images in HTML.</p>
121
  </div>
122
  <div class="bg-white p-3 rounded-lg shadow-sm">
123
- <h4 class="font-medium text-blue-600 mb-1">URL Encoding</h4>
124
- <p>Replaces unsafe ASCII characters with "%" followed by hexadecimal digits. Used in URLs.</p>
125
  </div>
126
  <div class="bg-white p-3 rounded-lg shadow-sm">
127
- <h4 class="font-medium text-blue-600 mb-1">HTML Entities</h4>
128
- <p>Represents special characters in HTML to prevent parsing issues and XSS attacks.</p>
129
  </div>
130
  </div>
131
  </div>
@@ -133,7 +185,12 @@
133
 
134
  <div class="mt-8 bg-white rounded-xl shadow-lg overflow-hidden">
135
  <div class="p-6">
136
- <h2 class="text-xl font-bold text-gray-800 mb-4">Recent Conversions</h2>
 
 
 
 
 
137
  <div class="overflow-x-auto">
138
  <table class="min-w-full divide-y divide-gray-200">
139
  <thead class="bg-gray-50">
@@ -142,6 +199,7 @@
142
  <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Input</th>
143
  <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Result</th>
144
  <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Time</th>
 
145
  </tr>
146
  </thead>
147
  <tbody class="bg-white divide-y divide-gray-200" id="history-table">
@@ -187,6 +245,67 @@
187
  </footer>
188
 
189
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  document.addEventListener('DOMContentLoaded', function() {
191
  // DOM elements
192
  const encodeTab = document.getElementById('encode-tab');
@@ -195,18 +314,27 @@
195
  const inputText = document.getElementById('input-text');
196
  const processBtn = document.getElementById('process-btn');
197
  const clearBtn = document.getElementById('clear-btn');
 
 
198
  const resultContainer = document.getElementById('result-container');
199
  const result = document.getElementById('result');
200
  const copyBtn = document.getElementById('copy-btn');
 
201
  const expandBtn = document.getElementById('expand-btn');
 
202
  const historyTable = document.getElementById('history-table');
203
  const emptyHistory = document.getElementById('empty-history');
 
204
 
205
  let isEncoding = true;
206
  let conversionHistory = JSON.parse(localStorage.getItem('conversionHistory')) || [];
207
 
208
  // Initialize
209
  updateHistoryTable();
 
 
 
 
210
 
211
  // Tab switching
212
  encodeTab.addEventListener('click', function() {
@@ -229,33 +357,85 @@
229
  const text = inputText.value.trim();
230
 
231
  if (!text) {
232
- alert('Please enter some text to process');
233
  return;
234
  }
235
 
236
  let processedText;
237
 
238
- if (isEncoding) {
239
- processedText = encodeText(text, method);
240
- } else {
241
- processedText = decodeText(text, method);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
  }
243
-
244
- result.textContent = processedText;
245
-
246
- // Add to history
247
- addToHistory(method, text, processedText);
248
  });
249
 
250
- // Clear button
251
  clearBtn.addEventListener('click', function() {
252
  inputText.value = '';
253
  result.textContent = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  });
255
 
256
  // Copy button
257
  copyBtn.addEventListener('click', function() {
258
- if (!result.textContent) return;
 
 
 
259
 
260
  navigator.clipboard.writeText(result.textContent)
261
  .then(() => {
@@ -264,12 +444,45 @@
264
  setTimeout(() => {
265
  copyBtn.innerHTML = originalIcon;
266
  }, 2000);
 
267
  })
268
  .catch(err => {
269
  console.error('Failed to copy text: ', err);
 
270
  });
271
  });
272
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
  // Expand button
274
  expandBtn.addEventListener('click', function() {
275
  resultContainer.classList.toggle('expanded');
@@ -280,11 +493,25 @@
280
  }
281
  });
282
 
 
 
 
 
 
 
 
 
 
 
 
 
283
  // Encoding/Decoding functions
284
  function encodeText(text, method) {
285
  switch(method) {
286
  case 'base64':
287
  return btoa(unescape(encodeURIComponent(text)));
 
 
288
  case 'url':
289
  return encodeURIComponent(text);
290
  case 'html':
@@ -307,6 +534,8 @@
307
  switch(method) {
308
  case 'base64':
309
  return decodeURIComponent(escape(atob(text)));
 
 
310
  case 'url':
311
  return decodeURIComponent(text);
312
  case 'html':
@@ -324,7 +553,7 @@
324
  return text;
325
  }
326
  } catch (e) {
327
- return `Error: ${e.message}`;
328
  }
329
  }
330
 
@@ -336,11 +565,12 @@
336
  output: output.length > 30 ? output.substring(0, 30) + '...' : output,
337
  fullInput: input,
338
  fullOutput: output,
339
- time: new Date().toLocaleTimeString()
 
340
  };
341
 
342
  conversionHistory.unshift(conversion);
343
- if (conversionHistory.length > 5) {
344
  conversionHistory.pop();
345
  }
346
 
@@ -358,20 +588,40 @@
358
  emptyHistory.style.display = 'none';
359
  historyTable.innerHTML = '';
360
 
361
- conversionHistory.forEach(item => {
362
  const row = document.createElement('tr');
363
- row.className = 'hover:bg-gray-50 cursor-pointer';
364
  row.innerHTML = `
365
  <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${item.method}</td>
366
  <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.input}</td>
367
  <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.output}</td>
368
- <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.time}</td>
 
 
 
 
 
 
 
 
 
 
 
369
  `;
370
 
371
- row.addEventListener('click', () => {
 
 
 
 
 
 
 
 
372
  methodSelect.value = item.method.toLowerCase();
373
  inputText.value = item.fullInput;
374
  result.textContent = item.fullOutput;
 
375
 
376
  // Set to decode if the output looks encoded
377
  if (item.fullOutput !== decodeText(item.fullOutput, item.method.toLowerCase())) {
@@ -386,9 +636,64 @@
386
  processBtn.innerHTML = '<i class="fas fa-cog mr-2"></i> Encode';
387
  }
388
  });
389
-
390
- historyTable.appendChild(row);
391
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
392
  }
393
  });
394
  </script>
 
37
  .copy-btn:active {
38
  transform: scale(0.95);
39
  }
40
+ .tooltip {
41
+ position: relative;
42
+ display: inline-block;
43
+ }
44
+ .tooltip .tooltiptext {
45
+ visibility: hidden;
46
+ width: 120px;
47
+ background-color: #555;
48
+ color: #fff;
49
+ text-align: center;
50
+ border-radius: 6px;
51
+ padding: 5px;
52
+ position: absolute;
53
+ z-index: 1;
54
+ bottom: 125%;
55
+ left: 50%;
56
+ margin-left: -60px;
57
+ opacity: 0;
58
+ transition: opacity 0.3s;
59
+ }
60
+ .tooltip:hover .tooltiptext {
61
+ visibility: visible;
62
+ opacity: 1;
63
+ }
64
+ .blink {
65
+ animation: blink-animation 1s steps(5, start) infinite;
66
+ }
67
+ @keyframes blink-animation {
68
+ to {
69
+ visibility: hidden;
70
+ }
71
+ }
72
  </style>
73
  </head>
74
  <body class="bg-gray-100 min-h-screen">
 
106
  <label for="method" class="block text-sm font-medium text-gray-700 mb-2">Encoding Method</label>
107
  <select id="method" class="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
108
  <option value="base64">Base64</option>
109
+ <option value="base32">Base32</option>
110
  <option value="url">URL Encoding</option>
111
  <option value="html">HTML Entities</option>
112
  <option value="hex">Hexadecimal</option>
 
117
 
118
  <div class="mb-6">
119
  <label for="input-text" class="block text-sm font-medium text-gray-700 mb-2">Input Text</label>
120
+ <div class="relative">
121
+ <textarea id="input-text" rows="5" class="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="Enter text to encode/decode..."></textarea>
122
+ <div class="absolute right-2 bottom-2 flex space-x-1">
123
+ <button id="sample-btn" class="tooltip bg-gray-100 text-gray-600 p-1 rounded hover:bg-gray-200">
124
+ <i class="fas fa-lightbulb"></i>
125
+ <span class="tooltiptext">Insert Sample</span>
126
+ </button>
127
+ <button id="clear-input-btn" class="tooltip bg-gray-100 text-gray-600 p-1 rounded hover:bg-gray-200">
128
+ <i class="fas fa-times"></i>
129
+ <span class="tooltiptext">Clear Input</span>
130
+ </button>
131
+ </div>
132
+ </div>
133
  </div>
134
 
135
  <div class="flex space-x-4 mb-6">
 
137
  <i class="fas fa-cog mr-2"></i> Process
138
  </button>
139
  <button id="clear-btn" class="flex-1 bg-gray-200 hover:bg-gray-300 text-gray-800 py-3 px-6 rounded-lg font-medium transition flex items-center justify-center">
140
+ <i class="fas fa-trash-alt mr-2"></i> Clear All
141
  </button>
142
  </div>
143
 
 
145
  <div class="flex justify-between items-center mb-3">
146
  <h3 class="font-medium text-gray-700">Result</h3>
147
  <div class="flex space-x-2">
148
+ <button id="download-btn" class="tooltip copy-btn bg-green-100 text-green-600 p-2 rounded-lg hover:bg-green-200">
149
+ <i class="fas fa-download"></i>
150
+ <span class="tooltiptext">Download Result</span>
151
+ </button>
152
+ <button id="copy-btn" class="tooltip copy-btn bg-blue-100 text-blue-600 p-2 rounded-lg hover:bg-blue-200">
153
  <i class="fas fa-copy"></i>
154
+ <span class="tooltiptext">Copy to Clipboard</span>
155
  </button>
156
+ <button id="expand-btn" class="tooltip copy-btn bg-gray-200 text-gray-600 p-2 rounded-lg hover:bg-gray-300">
157
  <i class="fas fa-expand"></i>
158
+ <span class="tooltiptext">Expand/Collapse</span>
159
  </button>
160
  </div>
161
  </div>
162
  <div id="result" class="text-gray-800 whitespace-pre-wrap break-words"></div>
163
+ <div id="char-count" class="text-xs text-gray-500 mt-2 text-right"></div>
164
  </div>
165
  </div>
166
 
 
169
  <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 text-sm text-gray-600">
170
  <div class="bg-white p-3 rounded-lg shadow-sm">
171
  <h4 class="font-medium text-blue-600 mb-1">Base64</h4>
172
+ <p>Encodes binary data to ASCII characters using 64 different characters (A-Z, a-z, 0-9, +, /). Commonly used for email attachments and embedding images in HTML.</p>
173
  </div>
174
  <div class="bg-white p-3 rounded-lg shadow-sm">
175
+ <h4 class="font-medium text-blue-600 mb-1">Base32</h4>
176
+ <p>Similar to Base64 but uses 32 different characters (A-Z, 2-7). More human-readable and case-insensitive, often used in OTP tokens and file hashes.</p>
177
  </div>
178
  <div class="bg-white p-3 rounded-lg shadow-sm">
179
+ <h4 class="font-medium text-blue-600 mb-1">URL Encoding</h4>
180
+ <p>Replaces unsafe ASCII characters with "%" followed by hexadecimal digits. Used in URLs to encode special characters.</p>
181
  </div>
182
  </div>
183
  </div>
 
185
 
186
  <div class="mt-8 bg-white rounded-xl shadow-lg overflow-hidden">
187
  <div class="p-6">
188
+ <div class="flex justify-between items-center mb-4">
189
+ <h2 class="text-xl font-bold text-gray-800">Recent Conversions</h2>
190
+ <button id="clear-history-btn" class="text-sm text-red-500 hover:text-red-700 flex items-center">
191
+ <i class="fas fa-trash-alt mr-1"></i> Clear History
192
+ </button>
193
+ </div>
194
  <div class="overflow-x-auto">
195
  <table class="min-w-full divide-y divide-gray-200">
196
  <thead class="bg-gray-50">
 
199
  <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Input</th>
200
  <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Result</th>
201
  <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Time</th>
202
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Action</th>
203
  </tr>
204
  </thead>
205
  <tbody class="bg-white divide-y divide-gray-200" id="history-table">
 
245
  </footer>
246
 
247
  <script>
248
+ // Base32 implementation
249
+ const Base32 = {
250
+ chars: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
251
+ pad: '=',
252
+
253
+ encode: function(input) {
254
+ if (!input) return '';
255
+
256
+ let output = '';
257
+ let buffer = 0;
258
+ let bitsLeft = 0;
259
+
260
+ for (let i = 0; i < input.length; i++) {
261
+ buffer = (buffer << 8) | input.charCodeAt(i);
262
+ bitsLeft += 8;
263
+
264
+ while (bitsLeft >= 5) {
265
+ bitsLeft -= 5;
266
+ output += this.chars.charAt((buffer >>> bitsLeft) & 0x1F);
267
+ }
268
+ }
269
+
270
+ if (bitsLeft > 0) {
271
+ buffer <<= (5 - bitsLeft);
272
+ output += this.chars.charAt(buffer & 0x1F);
273
+ }
274
+
275
+ // Add padding
276
+ const padCount = (8 - (output.length % 8)) % 8;
277
+ output += this.pad.repeat(padCount);
278
+
279
+ return output;
280
+ },
281
+
282
+ decode: function(input) {
283
+ if (!input) return '';
284
+
285
+ // Remove padding and convert to uppercase
286
+ input = input.replace(new RegExp(this.pad + '+$', 'g'), '').toUpperCase();
287
+
288
+ let output = '';
289
+ let buffer = 0;
290
+ let bitsLeft = 0;
291
+
292
+ for (let i = 0; i < input.length; i++) {
293
+ const index = this.chars.indexOf(input.charAt(i));
294
+ if (index === -1) continue;
295
+
296
+ buffer = (buffer << 5) | index;
297
+ bitsLeft += 5;
298
+
299
+ if (bitsLeft >= 8) {
300
+ bitsLeft -= 8;
301
+ output += String.fromCharCode((buffer >>> bitsLeft) & 0xFF);
302
+ }
303
+ }
304
+
305
+ return output;
306
+ }
307
+ };
308
+
309
  document.addEventListener('DOMContentLoaded', function() {
310
  // DOM elements
311
  const encodeTab = document.getElementById('encode-tab');
 
314
  const inputText = document.getElementById('input-text');
315
  const processBtn = document.getElementById('process-btn');
316
  const clearBtn = document.getElementById('clear-btn');
317
+ const clearInputBtn = document.getElementById('clear-input-btn');
318
+ const sampleBtn = document.getElementById('sample-btn');
319
  const resultContainer = document.getElementById('result-container');
320
  const result = document.getElementById('result');
321
  const copyBtn = document.getElementById('copy-btn');
322
+ const downloadBtn = document.getElementById('download-btn');
323
  const expandBtn = document.getElementById('expand-btn');
324
+ const charCount = document.getElementById('char-count');
325
  const historyTable = document.getElementById('history-table');
326
  const emptyHistory = document.getElementById('empty-history');
327
+ const clearHistoryBtn = document.getElementById('clear-history-btn');
328
 
329
  let isEncoding = true;
330
  let conversionHistory = JSON.parse(localStorage.getItem('conversionHistory')) || [];
331
 
332
  // Initialize
333
  updateHistoryTable();
334
+ updateCharCount();
335
+
336
+ // Event listeners for input changes
337
+ inputText.addEventListener('input', updateCharCount);
338
 
339
  // Tab switching
340
  encodeTab.addEventListener('click', function() {
 
357
  const text = inputText.value.trim();
358
 
359
  if (!text) {
360
+ showAlert('Please enter some text to process', 'error');
361
  return;
362
  }
363
 
364
  let processedText;
365
 
366
+ try {
367
+ if (isEncoding) {
368
+ processedText = encodeText(text, method);
369
+ } else {
370
+ processedText = decodeText(text, method);
371
+ }
372
+
373
+ result.textContent = processedText;
374
+ updateCharCount();
375
+
376
+ // Add to history
377
+ addToHistory(method, text, processedText);
378
+
379
+ // Show success message
380
+ showAlert('Operation completed successfully!', 'success');
381
+ } catch (e) {
382
+ result.textContent = `Error: ${e.message}`;
383
+ showAlert('An error occurred during processing', 'error');
384
  }
 
 
 
 
 
385
  });
386
 
387
+ // Clear buttons
388
  clearBtn.addEventListener('click', function() {
389
  inputText.value = '';
390
  result.textContent = '';
391
+ updateCharCount();
392
+ });
393
+
394
+ clearInputBtn.addEventListener('click', function() {
395
+ inputText.value = '';
396
+ updateCharCount();
397
+ inputText.focus();
398
+ });
399
+
400
+ // Sample button
401
+ sampleBtn.addEventListener('click', function() {
402
+ const method = methodSelect.value;
403
+ let sampleText = '';
404
+
405
+ switch(method) {
406
+ case 'base64':
407
+ case 'base32':
408
+ sampleText = 'Sample text to encode';
409
+ break;
410
+ case 'url':
411
+ sampleText = 'https://example.com/search?q=hello world';
412
+ break;
413
+ case 'html':
414
+ sampleText = '<div>Hello & Welcome</div>';
415
+ break;
416
+ case 'hex':
417
+ sampleText = '48656c6c6f20576f726c64';
418
+ break;
419
+ case 'binary':
420
+ sampleText = '01001000 01100101 01101100 01101100 01101111';
421
+ break;
422
+ case 'rot13':
423
+ sampleText = 'Uryyb Jbeyq';
424
+ break;
425
+ default:
426
+ sampleText = 'Sample text';
427
+ }
428
+
429
+ inputText.value = sampleText;
430
+ updateCharCount();
431
  });
432
 
433
  // Copy button
434
  copyBtn.addEventListener('click', function() {
435
+ if (!result.textContent) {
436
+ showAlert('No result to copy', 'error');
437
+ return;
438
+ }
439
 
440
  navigator.clipboard.writeText(result.textContent)
441
  .then(() => {
 
444
  setTimeout(() => {
445
  copyBtn.innerHTML = originalIcon;
446
  }, 2000);
447
+ showAlert('Copied to clipboard!', 'success');
448
  })
449
  .catch(err => {
450
  console.error('Failed to copy text: ', err);
451
+ showAlert('Failed to copy to clipboard', 'error');
452
  });
453
  });
454
 
455
+ // Download button
456
+ downloadBtn.addEventListener('click', function() {
457
+ if (!result.textContent) {
458
+ showAlert('No result to download', 'error');
459
+ return;
460
+ }
461
+
462
+ const method = methodSelect.value;
463
+ const isEncoded = isEncoding;
464
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
465
+ let filename = `codecipher_${timestamp}`;
466
+
467
+ if (isEncoded) {
468
+ filename += `_encoded.${method}`;
469
+ } else {
470
+ filename += `_decoded.txt`;
471
+ }
472
+
473
+ const blob = new Blob([result.textContent], { type: 'text/plain' });
474
+ const url = URL.createObjectURL(blob);
475
+ const a = document.createElement('a');
476
+ a.href = url;
477
+ a.download = filename;
478
+ document.body.appendChild(a);
479
+ a.click();
480
+ document.body.removeChild(a);
481
+ URL.revokeObjectURL(url);
482
+
483
+ showAlert('Download started!', 'success');
484
+ });
485
+
486
  // Expand button
487
  expandBtn.addEventListener('click', function() {
488
  resultContainer.classList.toggle('expanded');
 
493
  }
494
  });
495
 
496
+ // Clear history button
497
+ clearHistoryBtn.addEventListener('click', function() {
498
+ if (conversionHistory.length === 0) return;
499
+
500
+ if (confirm('Are you sure you want to clear all history?')) {
501
+ conversionHistory = [];
502
+ localStorage.setItem('conversionHistory', JSON.stringify(conversionHistory));
503
+ updateHistoryTable();
504
+ showAlert('History cleared', 'success');
505
+ }
506
+ });
507
+
508
  // Encoding/Decoding functions
509
  function encodeText(text, method) {
510
  switch(method) {
511
  case 'base64':
512
  return btoa(unescape(encodeURIComponent(text)));
513
+ case 'base32':
514
+ return Base32.encode(text);
515
  case 'url':
516
  return encodeURIComponent(text);
517
  case 'html':
 
534
  switch(method) {
535
  case 'base64':
536
  return decodeURIComponent(escape(atob(text)));
537
+ case 'base32':
538
+ return Base32.decode(text);
539
  case 'url':
540
  return decodeURIComponent(text);
541
  case 'html':
 
553
  return text;
554
  }
555
  } catch (e) {
556
+ throw new Error(`Invalid ${method} input: ${e.message}`);
557
  }
558
  }
559
 
 
565
  output: output.length > 30 ? output.substring(0, 30) + '...' : output,
566
  fullInput: input,
567
  fullOutput: output,
568
+ time: new Date().toLocaleTimeString(),
569
+ date: new Date().toLocaleDateString()
570
  };
571
 
572
  conversionHistory.unshift(conversion);
573
+ if (conversionHistory.length > 10) {
574
  conversionHistory.pop();
575
  }
576
 
 
588
  emptyHistory.style.display = 'none';
589
  historyTable.innerHTML = '';
590
 
591
+ conversionHistory.forEach((item, index) => {
592
  const row = document.createElement('tr');
593
+ row.className = 'hover:bg-gray-50';
594
  row.innerHTML = `
595
  <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${item.method}</td>
596
  <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.input}</td>
597
  <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">${item.output}</td>
598
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
599
+ <div>${item.time}</div>
600
+ <div class="text-xs text-gray-400">${item.date}</div>
601
+ </td>
602
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
603
+ <button class="history-action-btn p-1 text-blue-500 hover:text-blue-700" data-index="${index}">
604
+ <i class="fas fa-redo"></i>
605
+ </button>
606
+ <button class="history-delete-btn p-1 text-red-500 hover:text-red-700" data-index="${index}">
607
+ <i class="fas fa-trash-alt"></i>
608
+ </button>
609
+ </td>
610
  `;
611
 
612
+ historyTable.appendChild(row);
613
+ });
614
+
615
+ // Add event listeners to action buttons
616
+ document.querySelectorAll('.history-action-btn').forEach(btn => {
617
+ btn.addEventListener('click', function() {
618
+ const index = parseInt(this.getAttribute('data-index'));
619
+ const item = conversionHistory[index];
620
+
621
  methodSelect.value = item.method.toLowerCase();
622
  inputText.value = item.fullInput;
623
  result.textContent = item.fullOutput;
624
+ updateCharCount();
625
 
626
  // Set to decode if the output looks encoded
627
  if (item.fullOutput !== decodeText(item.fullOutput, item.method.toLowerCase())) {
 
636
  processBtn.innerHTML = '<i class="fas fa-cog mr-2"></i> Encode';
637
  }
638
  });
 
 
639
  });
640
+
641
+ document.querySelectorAll('.history-delete-btn').forEach(btn => {
642
+ btn.addEventListener('click', function() {
643
+ const index = parseInt(this.getAttribute('data-index'));
644
+ conversionHistory.splice(index, 1);
645
+ localStorage.setItem('conversionHistory', JSON.stringify(conversionHistory));
646
+ updateHistoryTable();
647
+ showAlert('Item removed from history', 'success');
648
+ });
649
+ });
650
+ }
651
+
652
+ // Helper functions
653
+ function updateCharCount() {
654
+ const inputLength = inputText.value.length;
655
+ const resultLength = result.textContent.length;
656
+
657
+ let countText = '';
658
+ if (inputLength > 0) {
659
+ countText += `Input: ${inputLength} chars`;
660
+ }
661
+ if (resultLength > 0) {
662
+ if (countText) countText += ' • ';
663
+ countText += `Result: ${resultLength} chars`;
664
+ }
665
+
666
+ charCount.textContent = countText;
667
+ }
668
+
669
+ function showAlert(message, type) {
670
+ // Remove any existing alerts
671
+ const existingAlert = document.querySelector('.alert-message');
672
+ if (existingAlert) {
673
+ existingAlert.remove();
674
+ }
675
+
676
+ const alert = document.createElement('div');
677
+ alert.className = `alert-message fixed top-4 right-4 px-4 py-2 rounded-lg shadow-lg text-white ${
678
+ type === 'success' ? 'bg-green-500' : 'bg-red-500'
679
+ } animate-bounce`;
680
+ alert.innerHTML = `
681
+ <div class="flex items-center">
682
+ <i class="fas ${type === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'} mr-2"></i>
683
+ <span>${message}</span>
684
+ </div>
685
+ `;
686
+
687
+ document.body.appendChild(alert);
688
+
689
+ // Auto-remove after 3 seconds
690
+ setTimeout(() => {
691
+ alert.classList.remove('animate-bounce');
692
+ alert.classList.add('opacity-0', 'transition-opacity', 'duration-300');
693
+ setTimeout(() => {
694
+ alert.remove();
695
+ }, 300);
696
+ }, 3000);
697
  }
698
  });
699
  </script>
prompts.txt ADDED
File without changes