vindree icon

Tag Sorter

vindree | PRO | 12/06/24 04:33:26 AM UTC (Edited) | 0 ⭐ | 853 👁️ | Never ⏰ | [html, text tool]
HTML |

6.78 KB

|

Source Code

|

0 👍

/

0 👎

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Tag sorter</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
      background-color: #f4f4f4;
    }
    h1 {
      color: #333;
    }
    textarea {
      width: 90%;
      max-width: 600px;
      height: 100px;
      margin-bottom: 10px;
      padding: 10px;
      font-size: 16px;
      border: 1px solid #ccc;
      border-radius: 5px;
    }
    .grid {
      display: flex;
      flex-wrap: wrap;
      gap: 10px;
      width: 90%;
      max-width: 600px;
      min-height: 100px;
      padding: 10px;
      background: #fff;
      border: 1px solid #ccc;
      border-radius: 5px;
      margin-bottom: 10px;
    }
    .block {
      padding: 10px 20px;
      background-color: #007BFF;
      color: white;
      border-radius: 5px;
      cursor: grab;
      user-select: none;
    }
    .block.duplicate {
      background-color: #FF5733;
    }
    .placeholder {
      width: 40px; /* About 2 characters wide */
      height: 20px; /* Matches block height */
      background-color: #ffeb3b;
      border-radius: 3px;
    }
    .controls {
      display: flex;
      gap: 10px;
      margin-bottom: 10px;
    }
    .controls button {
      padding: 10px 15px;
      background-color: #007BFF;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
    }
    .controls button:hover {
      background-color: #0056b3;
    }
    .last-moved {
      width: 90%;
      max-width: 600px;
      padding: 10px;
      background: #e8f5e9;
      border: 1px solid #a5d6a7;
      border-radius: 5px;
      font-size: 16px;
      color: #388e3c;
    }
  </style>
</head>
<body>
  <h1>Tag sorter</h1>
  <textarea id="input" placeholder="Enter comma-separated values here..."></textarea>
  <div class="controls">
    <button id="copy">Copy to Clipboard</button>
    <button id="sort-alpha">Sort Alphabetically</button>
    <button id="sort-length">Sort by Length</button>
  </div>
  <div class="grid" id="grid"></div>
  <div class="last-moved" id="lastMoved">Last moved block: <span id="lastMovedText">None</span></div>
 
  <script>
    const input = document.getElementById('input');
    const grid = document.getElementById('grid');
    const copyButton = document.getElementById('copy');
    const sortAlphaButton = document.getElementById('sort-alpha');
    const sortLengthButton = document.getElementById('sort-length');
    const lastMoved = document.getElementById('lastMovedText');
    let sortAlphaAscending = true;
    let sortLengthAscending = true;
 
    input.addEventListener('input', () => {
      const values = input.value.split(',').map(v => v.trim()).filter(v => v);
      renderBlocks(values);
    });
 
    const renderBlocks = (values) => {
      grid.innerHTML = ''; // Clear existing blocks
      values.forEach(value => {
        const block = document.createElement('div');
        block.className = 'block';
        block.textContent = value;
        block.draggable = true;
 
        // Drag and drop events
        block.addEventListener('dragstart', handleDragStart);
        block.addEventListener('dragover', handleDragOver);
        block.addEventListener('drop', handleDrop);
        block.addEventListener('dragend', handleDragEnd);
 
        grid.appendChild(block);
      });
      updateInput();
    };
 
    let draggedElement = null;
    let placeholder = null;
    let offsetX = 0;
    let offsetY = 0;
 
    const handleDragStart = (event) => {
      draggedElement = event.target;
 
      // Calculate offset between mouse and block position
      const rect = draggedElement.getBoundingClientRect();
      offsetX = event.clientX - rect.left;
      offsetY = event.clientY - rect.top;
 
      lastMoved.textContent = draggedElement.textContent;
      findDuplicates(draggedElement.textContent);
    };
 
    const handleDragOver = (event) => {
      event.preventDefault(); // Necessary for drop to work
      if (!placeholder) {
        placeholder = document.createElement('div');
        placeholder.className = 'placeholder';
      }
      const target = event.target;
      if (target.className.includes('block') && target !== draggedElement) {
        const rect = target.getBoundingClientRect();
        const dropPosition = event.clientX - rect.left + offsetX; // Adjust for offset
        if (dropPosition < rect.width / 2) {
          grid.insertBefore(placeholder, target);
        } else {
          grid.insertBefore(placeholder, target.nextSibling);
        }
      }
    };
 
    const handleDrop = (event) => {
      event.preventDefault();
      if (placeholder) {
        grid.insertBefore(draggedElement, placeholder);
        placeholder.remove();
        placeholder = null;
        updateInput();
      }
    };
 
    const handleDragEnd = () => {
      if (placeholder) {
        placeholder.remove();
        placeholder = null;
      }
    };
 
    const updateInput = () => {
      const blocks = Array.from(grid.children).map(block => block.textContent);
      input.value = blocks.join(', ');
    };
 
    const findDuplicates = (lastMovedText) => {
      const words = lastMovedText.split(' ');
      const blocks = Array.from(grid.children);
      blocks.forEach(block => {
        const blockWords = block.textContent.split(' ');
        const hasDuplicate = words.some(word => blockWords.includes(word));
        block.classList.toggle('duplicate', hasDuplicate);
      });
    };
 
    // Copy to Clipboard
    copyButton.addEventListener('click', () => {
      input.select();
      document.execCommand('copy');
      alert('Copied to clipboard!');
    });
 
    // Sort Alphabetically (Toggle between ascending and descending)
    sortAlphaButton.addEventListener('click', () => {
      const values = input.value.split(',').map(v => v.trim()).filter(v => v);
      values.sort((a, b) => sortAlphaAscending ? a.localeCompare(b) : b.localeCompare(a));
      sortAlphaAscending = !sortAlphaAscending; // Toggle the sort order
      renderBlocks(values);
    });
 
    // Sort by Length (Toggle between ascending and descending)
    sortLengthButton.addEventListener('click', () => {
      const values = input.value.split(',').map(v => v.trim()).filter(v => v);
      values.sort((a, b) => sortLengthAscending ? a.length - b.length : b.length - a.length);
      sortLengthAscending = !sortLengthAscending; // Toggle the sort order
      renderBlocks(values);
    });
</script>
 
</body>
</html>

Comments