Clipboard API

The modern Clipboard API provides secure access to clipboard operations, replacing the older document.execCommand() method.

Basic Clipboard Operations



html

<div class="clipboard-demo">
    <textarea id="text-input" placeholder="Type something to copy...">Hello, World!</textarea>
    <br><br>
    <button id="copy-btn">📋 Copy Text</button>
    <button id="paste-btn">📄 Paste Text</button>
    <button id="clear-btn">🗑️ Clear</button>
    
    <div id="status"></div>
</div>

<script>
const textInput = document.getElementById('text-input');
const copyBtn = document.getElementById('copy-btn');
const pasteBtn = document.getElementById('paste-btn');
const clearBtn = document.getElementById('clear-btn');
const status = document.getElementById('status');

// Copy text to clipboard
copyBtn.addEventListener('click', async () => {
    try {
        const text = textInput.value;
        await navigator.clipboard.writeText(text);
        showStatus('✅ Text copied to clipboard!', 'success');
    } catch (err) {
        showStatus('❌ Failed to copy text: ' + err.message, 'error');
        
        // Fallback for older browsers
        fallbackCopy(textInput.value);
    }
});

// Paste text from clipboard  
pasteBtn.addEventListener('click', async () => {
    try {
        const text = await navigator.clipboard.readText();
        textInput.value = text;
        showStatus('✅ Text pasted from clipboard!', 'success');
    } catch (err) {
        showStatus('❌ Failed to paste text: ' + err.message, 'error');
    }
});

// Clear text
clearBtn.addEventListener('click', () => {
    textInput.value = '';
    showStatus('🗑️ Text cleared', 'info');
});

// Fallback copy method for older browsers
function fallbackCopy(text) {
    const textArea = document.createElement('textarea');
    textArea.value = text;
    document.body.appendChild(textArea);
    textArea.select();
    
    try {
        document.execCommand('copy');
        showStatus('✅ Text copied to clipboard! (fallback)', 'success');
    } catch (err) {
        showStatus('❌ Copy failed', 'error');
    }
    
    document.body.removeChild(textArea);
}

// Status display function
function showStatus(message, type = 'info') {
    status.textContent = message;
    status.className = `status ${type}`;
    
    setTimeout(() => {
        status.textContent = '';
        status.className = '';
    }, 3000);
}

// Check clipboard API support
if (!navigator.clipboard) {
    showStatus('⚠️ Clipboard API not supported, using fallback', 'warning');
}
</script>

<style>
.clipboard-demo {
    padding: 20px;
    border: 1px solid #ddd;
    border-radius: 8px;
    margin: 20px 0;
}

#text-input {
    width: 100%;
    height: 100px;
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 4px;
    font-family: Arial, sans-serif;
}

button {
    padding: 10px 15px;
    margin: 5px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    background: #007bff;
    color: white;
}

button:hover {
    background: #0056b3;
}

.status {
    margin-top: 10px;
    padding: 8px;
    border-radius: 4px;
}

.status.success {
    background: #d4edda;
    color: #155724;
    border: 1px solid #c3e6cb;
}

.status.error {
    background: #f8d7da;
    color: #721c24;
    border: 1px solid #f5c6cb;
}

.status.warning {
    background: #fff3cd;
    color: #856404;
    border: 1px solid #ffeaa7;
}

.status.info {
    background: #d1ecf1;
    color: #0c5460;
    border: 1px solid #bee5eb;
}
</style>

Advanced Clipboard Operations



html

<div class="advanced-clipboard">
    <h3>Advanced Clipboard Demo</h3>
    
    <!-- Rich text editor -->
    <div id="editor" contenteditable="true" 
         style="border: 1px solid #ccc; padding: 10px; min-height: 100px; margin-bottom: 10px;">
        <p>This is <strong>rich text</strong> with <em>formatting</em>!</p>
        <p>You can copy and paste <span style="color: blue;">styled content</span>.</p>
    </div>
    
    <button id="copy-html">Copy HTML</button>
    <button id="paste-html">Paste HTML</button>
    <button id="copy-image">Copy Image</button>
    
    <!-- Image display -->
    <div id="image-container" style="margin-top: 15px;">
        <img id="demo-image" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iIzMwOThkYiIvPjx0ZXh0IHg9IjUwIiB5PSI1NSIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0IiBmaWxsPSJ3aGl0ZSIgdGV4dC1hbmNob3I9Im1pZGRsZSI+SW1hZ2U8L3RleHQ+PC9zdmc+" 
             alt="Demo image" style="max-width: 100px; margin: 10px 0;">
    </div>
    
    <div id="advanced-status"></div>
</div>

<script>
const editor = document.getElementById('editor');
const copyHtmlBtn = document.getElementById('copy-html');
const pasteHtmlBtn = document.getElementById('paste-html');
const copyImageBtn = document.getElementById('copy-image');
const demoImage = document.getElementById('demo-image');
const advancedStatus = document.getElementById('advanced-status');

// Copy HTML content
copyHtmlBtn.addEventListener('click', async () => {
    try {
        const html = editor.innerHTML;
        const plainText = editor.textContent;
        
        const clipboardItem = new ClipboardItem({
            'text/html': new Blob([html], { type: 'text/html' }),
            'text/plain': new Blob([plainText], { type: 'text/plain' })
        });
        
        await navigator.clipboard.write([clipboardItem]);
        showAdvancedStatus('✅ Rich content copied!', 'success');
    } catch (err) {
        showAdvancedStatus('❌ Failed to copy HTML: ' + err.message, 'error');
    }
});

// Paste HTML content
pasteHtmlBtn.addEventListener('click', async () => {
    try {
        const clipboardItems = await navigator.clipboard.read();
        
        for (const clipboardItem of clipboardItems) {
            // Try to get HTML first, then plain text
            if (clipboardItem.types.includes('text/html')) {
                const htmlBlob = await clipboardItem.getType('text/html');
                const html = await htmlBlob.text();
                editor.innerHTML = html;
                showAdvancedStatus('✅ Rich content pasted!', 'success');
            } else if (clipboardItem.types.includes('text/plain')) {
                const textBlob = await clipboardItem.getType('text/plain');
                const text = await textBlob.text();
                editor.textContent = text;
                showAdvancedStatus('✅ Plain text pasted!', 'success');
            }
        }
    } catch (err) {
        showAdvancedStatus('❌ Failed to paste: ' + err.message, 'error');
    }
});

// Copy image to clipboard
copyImageBtn.addEventListener('click', async () => {
    try {
        // Convert image to canvas then to blob
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        
        canvas.width = demoImage.naturalWidth || 100;
        canvas.height = demoImage.naturalHeight || 100;
        
        ctx.drawImage(demoImage, 0, 0);
        
        canvas.toBlob(async (blob) => {
            try {
                const clipboardItem = new ClipboardItem({
                    [blob.type]: blob
                });
                
                await navigator.clipboard.write([clipboardItem]);
                showAdvancedStatus('✅ Image copied to clipboard!', 'success');
            } catch (err) {
                showAdvancedStatus('❌ Failed to copy image: ' + err.message, 'error');
            }
        });
        
    } catch (err) {
        showAdvancedStatus('❌ Failed to process image: ' + err.message, 'error');
    }
});

function showAdvancedStatus(message, type) {
    advancedStatus.textContent = message;
    advancedStatus.className = `status ${type}`;
    
    setTimeout(() => {
        advancedStatus.textContent = '';
        advancedStatus.className = '';
    }, 3000);
}
</script>

Drag and Drop API

The HTML Drag and Drop API enables drag-and-drop functionality for web applications.

Basic Drag and Drop



html

<div class="drag-drop-demo">
    <h3>Basic Drag and Drop</h3>
    
    <div class="drag-container">
        <div class="draggable-item" draggable="true" data-item="apple">
            🍎 Apple
        </div>
        <div class="draggable-item" draggable="true" data-item="banana">
            🍌 Banana  
        </div>
        <div class="draggable-item" draggable="true" data-item="orange">
            🍊 Orange
        </div>
    </div>
    
    <div class="drop-zones">
        <div class="drop-zone" data-zone="fruits">
            <h4>Fruits Basket</h4>
            <div class="zone-content"></div>
        </div>
        
        <div class="drop-zone" data-zone="trash">
            <h4>🗑️ Trash</h4>
            <div class="zone-content"></div>
        </div>
    </div>
    
    <button id="reset-items">Reset Items</button>
</div>

<style>
.drag-drop-demo {
    padding: 20px;
    border: 1px solid #ddd;
    border-radius: 8px;
    margin: 20px 0;
}

.drag-container {
    display: flex;
    gap: 10px;
    margin: 20px 0;
    padding: 15px;
    background: #f8f9fa;
    border-radius: 8px;
}

.draggable-item {
    padding: 15px 20px;
    background: #ffffff;
    border: 2px solid #dee2e6;
    border-radius: 8px;
    cursor: grab;
    user-select: none;
    transition: all 0.2s ease;
}

.draggable-item:hover {
    background: #e9ecef;
    transform: translateY(-2px);
}

.draggable-item.dragging {
    opacity: 0.5;
    transform: rotate(5deg);
}

.drop-zones {
    display: flex;
    gap: 20px;
    margin: 20px 0;
}

.drop-zone {
    flex: 1;
    min-height: 150px;
    border: 3px dashed #ced4da;
    border-radius: 8px;
    padding: 15px;
    background: #f8f9fa;
    transition: all 0.3s ease;
}

.drop-zone.drag-over {
    border-color: #007bff;
    background: #e3f2fd;
}

.drop-zone h4 {
    margin: 0 0 10px 0;
    color: #495057;
    text-align: center;
}

.zone-content {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.zone-content .draggable-item {
    margin: 0;
}

#reset-items {
    padding: 10px 20px;
    background: #28a745;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}
</style>

<script>
let draggedElement = null;

// Get all draggable items and drop zones
const draggableItems = document.querySelectorAll('.draggable-item');
const dropZones = document.querySelectorAll('.drop-zone');
const resetBtn = document.getElementById('reset-items');

// Add drag event listeners to draggable items
draggableItems.forEach(item => {
    item.addEventListener('dragstart', handleDragStart);
    item.addEventListener('dragend', handleDragEnd);
});

// Add drop event listeners to drop zones
dropZones.forEach(zone => {
    zone.addEventListener('dragover', handleDragOver);
    zone.addEventListener('dragenter', handleDragEnter);
    zone.addEventListener('dragleave', handleDragLeave);
    zone.addEventListener('drop', handleDrop);
});

function handleDragStart(e) {
    draggedElement = this;
    this.classList.add('dragging');
    
    // Set drag data
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('text/html', this.outerHTML);
    e.dataTransfer.setData('text/plain', this.textContent);
    e.dataTransfer.setData('application/x-item-id', this.dataset.item);
}

function handleDragEnd(e) {
    this.classList.remove('dragging');
    draggedElement = null;
}

function handleDragOver(e) {
    if (e.preventDefault) {
        e.preventDefault();
    }
    
    e.dataTransfer.dropEffect = 'move';
    return false;
}

function handleDragEnter(e) {
    this.classList.add('drag-over');
}

function handleDragLeave(e) {
    this.classList.remove('drag-over');
}

function handleDrop(e) {
    if (e.stopPropagation) {
        e.stopPropagation();
    }
    
    this.classList.remove('drag-over');
    
    if (draggedElement) {
        // Move the element to the drop zone
        const zoneContent = this.querySelector('.zone-content');
        const clonedElement = draggedElement.cloneNode(true);
        
        // Add event listeners to the cloned element
        clonedElement.addEventListener('dragstart', handleDragStart);
        clonedElement.addEventListener('dragend', handleDragEnd);
        
        zoneContent.appendChild(clonedElement);
        
        // Remove original element
        draggedElement.remove();
        
        // Special handling for trash zone
        if (this.dataset.zone === 'trash') {
            setTimeout(() => {
                clonedElement.style.animation = 'fadeOut 0.5s ease-out forwards';
                setTimeout(() => clonedElement.remove(), 500);
            }, 100);
        }
    }
    
    return false;
}

// Reset functionality
resetBtn.addEventListener('click', () => {
    // Clear all drop zones
    document.querySelectorAll('.zone-content').forEach(content => {
        content.innerHTML = '';
    });
    
    // Restore original items
    const dragContainer = document.querySelector('.drag-container');
    dragContainer.innerHTML = `
        <div class="draggable-item" draggable="true" data-item="apple">🍎 Apple</div>
        <div class="draggable-item" draggable="true" data-item="banana">🍌 Banana</div>
        <div class="draggable-item" draggable="true" data-item="orange">🍊 Orange</div>
    `;
    
    // Re-add event listeners
    dragContainer.querySelectorAll('.draggable-item').forEach(item => {
        item.addEventListener('dragstart', handleDragStart);
        item.addEventListener('dragend', handleDragEnd);
    });
});

// Add CSS animation for fade out
const style = document.createElement('style');
style.textContent = `
    @keyframes fadeOut {
        from { opacity: 1; transform: scale(1); }
        to { opacity: 0; transform: scale(0.8); }
    }
`;
document.head.appendChild(style);
</script>

File Upload with Drag and Drop



html

<div class="file-upload-demo">
    <h3>File Upload with Drag & Drop</h3>
    
    <div id="drop-area" class="drop-area">
        <div class="upload-icon">📁</div>
        <p>Drag and drop files here or <button id="file-select">Browse Files</button></p>
        <input type="file" id="file-input" multiple accept="image/*,text/*,.pdf" style="display: none;">
        <div class="upload-info">Supported: Images, Text files, PDFs</div>
    </div>
    
    <div id="file-list" class="file-list"></div>
    
    <div class="upload-actions">
        <button id="upload-files" style="display: none;">Upload Selected Files</button>
        <button id="clear-files" style="display: none;">Clear All</button>
    </div>
    
    <div class="upload-progress" id="upload-progress" style="display: none;">
        <div class="progress-bar">
            <div class="progress-fill" id="progress-fill"></div>
        </div>
        <div class="progress-text" id="progress-text">0%</div>
    </div>
</div>

<style>
.file-upload-demo {
    padding: 20px;
    border: 1px solid #ddd;
    border-radius: 8px;
    margin: 20px 0;
}

.drop-area {
    border: 3px dashed #ccc;
    border-radius: 12px;
    padding: 40px;
    text-align: center;
    background: #fafafa;
    transition: all 0.3s ease;
    cursor: pointer;
}

.drop-area.drag-over {
    border-color: #007bff;
    background: #e3f2fd;
    transform: scale(1.02);
}

.upload-icon {
    font-size: 3em;
    margin-bottom: 15px;
}

.drop-area p {
    font-size: 1.1em;
    color: #666;
    margin: 10px 0;
}

#file-select {
    background: #007bff;
    color: white;
    border: none;
    padding: 8px 16px;
    border-radius: 4px;
    cursor: pointer;
}

.upload-info {
    font-size: 0.9em;
    color: #999;
    margin-top: 10px;
}

.file-list {
    margin: 20px 0;
    max-height: 300px;
    overflow-y: auto;
}

.file-item {
    display: flex;
    align-items: center;
    gap: 15px;
    padding: 12px;
    border: 1px solid #e0e0e0;
    border-radius: 8px;
    margin-bottom: 8px;
    background: white;
}

.file-icon {
    font-size: 1.5em;
    min-width: 30px;
}

.file-info {
    flex: 1;
}

.file-name {
    font-weight: bold;
    color: #333;
}

.file-size {
    font-size: 0.9em;
    color: #666;
}

.file-preview {
    max-width: 60px;
    max-height: 60px;
    border-radius: 4px;
}

.file-remove {
    background: #dc3545;
    color: white;
    border: none;
    padding: 5px 10px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 0.8em;
}

.upload-actions {
    margin: 20px 0;
    text-align: center;
}

.upload-actions button {
    margin: 0 10px;
    padding: 10px 20px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

#upload-files {
    background: #28a745;
    color: white;
}

#clear-files {
    background: #6c757d;
    color: white;
}

.upload-progress {
    margin: 20px 0;
}

.progress-bar {
    width: 100%;
    height: 20px;
    background: #e0e0e0;
    border-radius: 10px;
    overflow: hidden;
    margin-bottom: 8px;
}

.progress-fill {
    height: 100%;
    background: linear-gradient(90deg, #007bff, #0056b3);
    border-radius: 10px;
    width: 0%;
    transition: width 0.3s ease;
}

.progress-text {
    text-align: center;
    font-weight: bold;
    color: #333;
}
</style>

<script>
class FileUploader {
    constructor() {
        this.files = [];
        this.initializeElements();
        this.addEventListeners();
    }
    
    initializeElements() {
        this.dropArea = document.getElementById('drop-area');
        this.fileInput = document.getElementById('file-input');
        this.fileSelect = document.getElementById('file-select');
        this.fileList = document.getElementById('file-list');
        this.uploadBtn = document.getElementById('upload-files');
        this.clearBtn = document.getElementById('clear-files');
        this.progressContainer = document.getElementById('upload-progress');
        this.progressFill = document.getElementById('progress-fill');
        this.progressText = document.getElementById('progress-text');
    }
    
    addEventListeners() {
        // Drop area events
        this.dropArea.addEventListener('dragover', this.handleDragOver.bind(this));
        this.dropArea.addEventListener('dragenter', this.handleDragEnter.bind(this));
        this.dropArea.addEventListener('dragleave', this.handleDragLeave.bind(this));
        this.dropArea.addEventListener('drop', this.handleDrop.bind(this));
        this.dropArea.addEventListener('click', () => this.fileInput.click());
        
        // File input events
        this.fileInput.addEventListener('change', this.handleFileSelect.bind(this));
        this.fileSelect.addEventListener('click', (e) => {
            e.stopPropagation();
            this.fileInput.click();
        });
        
        // Button events
        this.uploadBtn.addEventListener('click', this.uploadFiles.bind(this));
        this.clearBtn.addEventListener('click', this.clearFiles.bind(this));
    }
    
    handleDragOver(e) {
        e.preventDefault();
        e.dataTransfer.dropEffect = 'copy';
    }
    
    handleDragEnter(e) {
        e.preventDefault();
        this.dropArea.classList.add('drag-over');
    }
    
    handleDragLeave(e) {
        e.preventDefault();
        this.dropArea.classList.remove('drag-over');
    }
    
    handleDrop(e) {
        e.preventDefault();
        this.dropArea.classList.remove('drag-over');
        
        const files = Array.from(e.dataTransfer.files);
        this.addFiles(files);
    }
    
    handleFileSelect(e) {
        const files = Array.from(e.target.files);
        this.addFiles(files);
        e.target.value = ''; // Reset input
    }
    
    addFiles(newFiles) {
        // Filter and validate files
        const validFiles = newFiles.filter(file => {
            if (file.size > 10 * 1024 * 1024) { // 10MB limit
                alert(`File "${file.name}" is too large (max 10MB)`);
                return false;
            }
            
            // Check if file already exists
            const exists = this.files.some(existingFile => 
                existingFile.name === file.name && existingFile.size === file.size
            );
            
            if (exists) {
                alert(`File "${file.name}" already added`);
                return false;
            }
            
            return true;
        });
        
        this.files.push(...validFiles);
        this.updateFileList();
        this.updateButtons();
    }
    
    updateFileList() {
        this.fileList.innerHTML = '';
        
        this.files.forEach((file, index) => {
            const fileItem = document.createElement('div');
            fileItem.className = 'file-item';
            
            const fileIcon = this.getFileIcon(file.type);
            const fileSize = this.formatFileSize(file.size);
            
            fileItem.innerHTML = `
                <div class="file-icon">${fileIcon}</div>
                <div class="file-info">
                    <div class="file-name">${file.name}</div>
                    <div class="file-size">${fileSize}</div>
                </div>
                ${file.type.startsWith('image/') ? 
                    `<img class="file-preview" src="${URL.createObjectURL(file)}" alt="Preview">` : 
                    ''}
                <button class="file-remove" onclick="fileUploader.removeFile(${index})">Remove</button>
            `;
            
            this.fileList.appendChild(fileItem);
        });
    }
    
    getFileIcon(mimeType) {
        if (mimeType.startsWith('image/')) return '🖼️';
        if (mimeType.startsWith('text/')) return '📄';
        if (mimeType === 'application/pdf') return '📕';
        if (mimeType.startsWith('video/')) return '🎥';
        if (mimeType.startsWith('audio/')) return '🎵';
        return '📁';
    }
    
    formatFileSize(bytes) {
        if (bytes === 0) return '0 Bytes';
        const k = 1024;
        const sizes = ['Bytes', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }
    
    removeFile(index) {
        this.files.splice(index, 1);
        this.updateFileList();
        this.updateButtons();
    }
    
    updateButtons() {
        const hasFiles = this.files.length > 0;
        this.uploadBtn.style.display = hasFiles ? 'inline-block' : 'none';
        this.clearBtn.style.display = hasFiles ? 'inline-block' : 'none';
    }
    
    clearFiles() {
        this.files = [];
        this.updateFileList();
        this.updateButtons();
        this.hideProgress();
    }
    
    async uploadFiles() {
        if (this.files.length === 0) return;
        
        this.showProgress();
        this.uploadBtn.disabled = true;
        
        try {
            for (let i = 0; i < this.files.length; i++) {
                const file = this.files[i];
                await this.uploadFile(file);
                
                const progress = ((i + 1) / this.files.length) * 100;
                this.updateProgress(progress);
            }
            
            alert('All files uploaded successfully!');
            this.clearFiles();
            
        } catch (error) {
            alert('Upload failed: ' + error.message);
        } finally {
            this.uploadBtn.disabled = false;
            this.hideProgress();
        }
    }
    
    async uploadFile(file) {
        // Simulate file upload with delay
        return new Promise((resolve) => {
            setTimeout(() => {
                console.log(`Uploaded: ${file.name}`);
                resolve();
            }, 1000);
        });
        
        // Real upload implementation would look like:
        /*
        const formData = new FormData();
        formData.append('file', file);
        
        const response = await fetch('/upload', {
            method: 'POST',
            body: formData
        });
        
        if (!response.ok) {
            throw new Error('Upload failed');
        }
        
        return response.json();
        */
    }
    
    showProgress() {
        this.progressContainer.style.display = 'block';
        this.updateProgress(0);
    }
    
    hideProgress() {
        this.progressContainer.style.display = 'none';
    }
    
    updateProgress(percentage) {
        this.progressFill.style.width = percentage + '%';
        this.progressText.textContent = Math.round(percentage) + '%';
    }
}

// Initialize file uploader
const fileUploader = new FileUploader();
</script>

Advanced Drag and Drop Features



html

<div class="advanced-drag-drop">
    <h3>Advanced Drag & Drop Features</h3>
    
    <!-- Sortable list -->
    <div class="sortable-container">
        <h4>Sortable Task List</h4>
        <ul id="sortable-list" class="sortable-list">
            <li class="sortable-item" draggable="true">
                <span class="drag-handle">⋮⋮</span>
                <span>Complete project proposal</span>
            </li>
            <li class="sortable-item" draggable="true">
                <span class="drag-handle">⋮⋮</span>
                <span>Review client feedback</span>
            </li>
            <li class="sortable-item" draggable="true">
                <span class="drag-handle">⋮⋮</span>
                <span>Update website design</span>
            </li>
            <li class="sortable-item" draggable="true">
                <span class="drag-handle">⋮⋮</span>
                <span>Prepare presentation slides</span>
            </li>
        </ul>
    </div>
    
    <!-- Kanban board -->
    <div class="kanban-board">
        <h4>Kanban Board</h4>
        <div class="kanban-columns">
            <div class="kanban-column" data-status="todo">
                <h5>To Do</h5>
                <div class="kanban-cards">
                    <div class="kanban-card" draggable="true" data-card="1">
                        <div class="card-title">Design Homepage</div>
                        <div class="card-meta">Due: Jan 25</div>
                    </div>
                    <div class="kanban-card" draggable="true" data-card="2">
                        <div class="card-title">Write Documentation</div>
                        <div class="card-meta">Due: Jan 30</div>
                    </div>
                </div>
            </div>
            
            <div class="kanban-column" data-status="progress">
                <h5>In Progress</h5>
                <div class="kanban-cards">
                    <div class="kanban-card" draggable="true" data-card="3">
                        <div class="card-title">API Development</div>
                        <div class="card-meta">Started: Jan 20</div>
                    </div>
                </div>
            </div>
            
            <div class="kanban-column" data-status="done">
                <h5>Done</h5>
                <div class="kanban-cards">
                    <div class="kanban-card" draggable="true" data-card="4">
                        <div class="card-title">Setup Development Environment</div>
                        <div class="card-meta">Completed: Jan 18</div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<style>
.advanced-drag-drop {
    padding: 20px;
    border: 1px solid #ddd;
    border-radius: 8px;
    margin: 20px 0;
}

.sortable-container, .kanban-board {
    margin: 20px 0;
    padding: 15px;
    background: #f8f9fa;
    border-radius: 8px;
}

.sortable-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.sortable-item {
    display: flex;
    align-items: center;
    padding: 12px;
    margin: 8px 0;
    background: white;
    border: 1px solid #dee2e6;
    border-radius: 6px;
    cursor: move;
    transition: all 0.2s ease;
}

.sortable-item:hover {
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    transform: translateY(-1px);
}

.sortable-item.dragging {
    opacity: 0.5;
}

.drag-handle {
    color: #6c757d;
    margin-right: 10px;
    cursor: grab;
}

.kanban-columns {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 20px;
}

.kanban-column {
    background: white;
    border-radius: 8px;
    padding: 15px;
    border: 1px solid #e0e0e0;
}

.kanban-column h5 {
    margin: 0 0 15px 0;
    padding: 8px;
    background: #f1f3f4;
    border-radius: 4px;
    text-align: center;
    color: #333;
}

.kanban-cards {
    min-height: 100px;
}

.kanban-card {
    background: #fff;
    border: 1px solid #d1d5db;
    border-radius: 6px;
    padding: 12px;
    margin: 8px 0;
    cursor: move;
    transition: all 0.2s ease;
}

.kanban-card:hover {
    box-shadow: 0 2px 8px rgba(0,0,0,0.15);
}

.kanban-card.dragging {
    opacity: 0.5;
    transform: rotate(3deg);
}

.kanban-column.drag-over {
    background: #e3f2fd;
    border-color: #2196f3;
}

.card-title {
    font-weight: bold;
    margin-bottom: 6px;
    color: #333;
}

.card-meta {
    font-size: 0.85em;
    color: #666;
}
</style>

<script>
class AdvancedDragDrop {
    constructor() {
        this.setupSortableList();
        this.setupKanbanBoard();
    }
    
    setupSortableList() {
        const list = document.getElementById('sortable-list');
        let draggedItem = null;
        
        list.addEventListener('dragstart', (e) => {
            if (e.target.classList.contains('sortable-item')) {
                draggedItem = e.target;
                e.target.classList.add('dragging');
                e.dataTransfer.effectAllowed = 'move';
            }
        });
        
        list.addEventListener('dragend', (e) => {
            if (e.target.classList.contains('sortable-item')) {
                e.target.classList.remove('dragging');
                draggedItem = null;
            }
        });
        
        list.addEventListener('dragover', (e) => {
            e.preventDefault();
            const afterElement = this.getDragAfterElement(list, e.clientY);
            
            if (afterElement == null) {
                list.appendChild(draggedItem);
            } else {
                list.insertBefore(draggedItem, afterElement);
            }
        });
    }
    
    getDragAfterElement(container, y) {
        const draggableElements = [...container.querySelectorAll('.sortable-item:not(.dragging)')];
        
        return draggableElements.reduce((closest, child) => {
            const box = child.getBoundingClientRect();
            const offset = y - box.top - box.height / 2;
            
            if (offset < 0 && offset > closest.offset) {
                return { offset: offset, element: child };
            } else {
                return closest;
            }
        }, { offset: Number.NEGATIVE_INFINITY }).element;
    }
    
    setupKanbanBoard() {
        const columns = document.querySelectorAll('.kanban-column');
        const cards = document.querySelectorAll('.kanban-card');
        let draggedCard = null;
        
        // Add drag events to cards
        cards.forEach(card => {
            card.addEventListener('dragstart', (e) => {
                draggedCard = e.target;
                e.target.classList.add('dragging');
                e.dataTransfer.setData('text/plain', e.target.dataset.card);
            });
            
            card.addEventListener('dragend', (e) => {
                e.target.classList.remove('dragging');
                draggedCard = null;
            });
        });
        
        // Add drop events to columns
        columns.forEach(column => {
            column.addEventListener('dragover', (e) => {
                e.preventDefault();
                e.dataTransfer.dropEffect = 'move';
            });
            
            column.addEventListener('dragenter', (e) => {
                e.preventDefault();
                column.classList.add('drag-over');
            });
            
            column.addEventListener('dragleave', (e) => {
                if (!column.contains(e.relatedTarget)) {
                    column.classList.remove('drag-over');
                }
            });
            
            column.addEventListener('drop', (e) => {
                e.preventDefault();
                column.classList.remove('drag-over');
                
                if (draggedCard) {
                    const cardsContainer = column.querySelector('.kanban-cards');
                    cardsContainer.appendChild(draggedCard);
                    
                    // Update card status based on column
                    const newStatus = column.dataset.status;
                    console.log(`Card ${draggedCard.dataset.card} moved to ${newStatus}`);
                }
            });
        });
    }
}

// Initialize advanced drag and drop
const advancedDragDrop = new AdvancedDragDrop();
</script>

Integration Examples

Copy-Paste with Drag-Drop



html

<div class="integration-demo">
    <h3>Copy-Paste + Drag-Drop Integration</h3>
    
    <div class="demo-areas">
        <div class="content-area">
            <h4>Content Creator</h4>
            <textarea id="content-input" placeholder="Create some content...">Sample text content</textarea>
            <button id="copy-content">📋 Copy Content</button>
        </div>
        
        <div class="workspace">
            <h4>Workspace</h4>
            <div id="workspace-area" class="workspace-area">
                <div class="workspace-item" draggable="true">
                    📝 Draggable Note 1
                </div>
                <div class="workspace-item" draggable="true">
                    📝 Draggable Note 2
                </div>
            </div>
            <button id="paste-content">📄 Paste Here</button>
            <button id="add-from-clipboard">➕ Add from Clipboard</button>
        </div>
    </div>
</div>

<style>
.integration-demo {
    padding: 20px;
    border: 1px solid #ddd;
    border-radius: 8px;
    margin: 20px 0;
}

.demo-areas {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
}

.content-area, .workspace {
    padding: 15px;
    border: 1px solid #e0e0e0;
    border-radius: 8px;
}

#content-input {
    width: 100%;
    height: 100px;
    margin-bottom: 10px;
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 4px;
}

.workspace-area {
    min-height: 150px;
    border: 2px dashed #ccc;
    border-radius: 8px;
    padding: 15px;
    margin-bottom: 10px;
}

.workspace-item {
    display: inline-block;
    padding: 8px 12px;
    margin: 4px;
    background: #e3f2fd;
    border: 1px solid #2196f3;
    border-radius: 4px;
    cursor: move;
}

.workspace-item.dragging {
    opacity: 0.5;
}
</style>

<script>
class IntegratedDemo {
    constructor() {
        this.setupElements();
        this.addEventListeners();
    }
    
    setupElements() {
        this.contentInput = document.getElementById('content-input');
        this.copyBtn = document.getElementById('copy-content');
        this.pasteBtn = document.getElementById('paste-content');
        this.addBtn = document.getElementById('add-from-clipboard');
        this.workspace = document.getElementById('workspace-area');
    }
    
    addEventListeners() {
        this.copyBtn.addEventListener('click', this.copyContent.bind(this));
        this.pasteBtn.addEventListener('click', this.pasteContent.bind(this));
        this.addBtn.addEventListener('click', this.addFromClipboard.bind(this));
        
        // Drag and drop for workspace items
        this.workspace.addEventListener('dragstart', this.handleDragStart.bind(this));
        this.workspace.addEventListener('dragover', this.handleDragOver.bind(this));
        this.workspace.addEventListener('drop', this.handleDrop.bind(this));
    }
    
    async copyContent() {
        try {
            await navigator.clipboard.writeText(this.contentInput.value);
            this.showStatus('Content copied to clipboard!');
        } catch (err) {
            console.error('Copy failed:', err);
        }
    }
    
    async pasteContent() {
        try {
            const text = await navigator.clipboard.readText();
            this.contentInput.value = text;
            this.showStatus('Content pasted from clipboard!');
        } catch (err) {
            console.error('Paste failed:', err);
        }
    }
    
    async addFromClipboard() {
        try {
            const text = await navigator.clipboard.readText();
            if (text.trim()) {
                const item = document.createElement('div');
                item.className = 'workspace-item';
                item.draggable = true;
                item.textContent = '📋 ' + text.substring(0, 30) + (text.length > 30 ? '...' : '');
                this.workspace.appendChild(item);
                this.showStatus('Added item from clipboard!');
            }
        } catch (err) {
            console.error('Add from clipboard failed:', err);
        }
    }
    
    handleDragStart(e) {
        if (e.target.classList.contains('workspace-item')) {
            e.target.classList.add('dragging');
            e.dataTransfer.setData('text/plain', e.target.textContent);
        }
    }
    
    handleDragOver(e) {
        e.preventDefault();
    }
    
    handleDrop(e) {
        e.preventDefault();
        const draggedItem = this.workspace.querySelector('.dragging');
        if (draggedItem) {
            draggedItem.classList.remove('dragging');
            // Reorder logic could be added here
        }
    }
    
    showStatus(message) {
        // Simple status display
        console.log(message);
        
        // You could add a toast notification here
        const toast = document.createElement('div');
        toast.textContent = message;
        toast.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            background: #28a745;
            color: white;
            padding: 10px 15px;
            border-radius: 4px;
            z-index: 1000;
        `;
        document.body.appendChild(toast);
        
        setTimeout(() => toast.remove(), 3000);
    }
}

const integratedDemo = new IntegratedDemo();
</script>