I am working on a website that can generate templates with drag and drop. I have made an element generator. But the problem is that I can only drag and drop the elements that are already in the “container” as an example ” already button” but the generated items are not droppable. I’m new to JavaScript so don’t know much about it. Please solve this problem. So I may continue to work on my website Here is my code
<html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <style> body { margin: 0; } .container { background-color: #333; padding: 1rem; margin-top: 1rem; } .draggable { padding: 1rem; background-color: white; border: 1px solid black; cursor: move; } .draggable.dragging { opacity: .5; } /* Background Styles Only */ @import url('https://fonts.googleapis.com/css?family=Raleway'); * { font-family: Raleway; } .side-links { position: absolute; top: 15px; right: 15px; } .side-link { display: flex; align-items: center; justify-content: center; text-decoration: none; margin-bottom: 10px; color: white; width: 180px; padding: 10px 0; border-radius: 10px; } .side-link-youtube { background-color: red; } .side-link-twitter { background-color: #1DA1F2; } .side-link-github { background-color: #6e5494; } .side-link-text { margin-left: 10px; font-size: 18px; } .side-link-icon { color: white; font-size: 30px; } </style> <body> <textarea id="ambtnhtml" name="generatedCode1" class="generatedCode1"> <button type="button" class="draggable" id="" draggable ="true"> Button</button></textarea> <!-- area --> <button type="button" id="generatehtml">generate button </button> <div class="container pipp" style="margin: auto;"> <button type="button" class="draggable AM-btnhj" id="" draggable="true">Already Button</button> </div> <div class="container"> </div> </body> <!-- drag and drop able script --> <script> const draggables = document.querySelectorAll('.draggable') const containers = document.querySelectorAll('.container') draggables.forEach(draggable => { draggable.addEventListener('dragstart', () => { draggable.classList.add('dragging') }) draggable.addEventListener('dragend', () => { draggable.classList.remove('dragging') }) }) containers.forEach(container => { container.addEventListener('dragover', e => { e.preventDefault() const afterElement = getDragAfterElement(container, e.clientY) const draggable = document.querySelector('.dragging') if (afterElement == null) { container.appendChild(draggable) } else { container.insertBefore(draggable, afterElement) } }) }) function getDragAfterElement(container, y) { const draggableElements = [...container.querySelectorAll('.draggable: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 } </script> <!-- add new button --> <script src="http://code.jquery.com/jquery-1.8.1.min.js"></script> <script> $(document).ready(function() { $("#generatehtml").click(function() { $(".pipp").append($("#ambtnhtml").val()); $("ambtnhtml").val(""); }); }); </script> </html>
Please Help
Advertisement
Answer
You missed adding event handlers to the new elements. I modified your example by adding event handlers to a separate function initDraggable
so that later it would be easier to use it when generating new elements.
<html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <style> body { margin: 0; } .container { background-color: #333; padding: 1rem; margin-top: 1rem; } .draggable { padding: 1rem; background-color: white; border: 1px solid black; cursor: move; } .draggable.dragging { opacity: .5; } /* Background Styles Only */ @import url('https://fonts.googleapis.com/css?family=Raleway'); * { font-family: Raleway; } .side-links { position: absolute; top: 15px; right: 15px; } .side-link { display: flex; align-items: center; justify-content: center; text-decoration: none; margin-bottom: 10px; color: white; width: 180px; padding: 10px 0; border-radius: 10px; } .side-link-youtube { background-color: red; } .side-link-twitter { background-color: #1DA1F2; } .side-link-github { background-color: #6e5494; } .side-link-text { margin-left: 10px; font-size: 18px; } .side-link-icon { color: white; font-size: 30px; } </style> <body> <textarea id="ambtnhtml" name="generatedCode1" class="generatedCode1"> <button type="button" class="draggable" id="" draggable ="true"> Button</button></textarea> <!-- area --> <button type="button" id="generatehtml">generate button </button> <div class="container pipp" style="margin: auto;"> <button type="button" class="draggable AM-btnhj" id="" draggable="true">Already Button</button> </div> <div class="container"> </div> </body> <!-- drag and drop able script --> <script> const draggables = document.querySelectorAll('.draggable') const containers = document.querySelectorAll('.container') function initDraggable (draggable) { draggable.addEventListener('dragstart', () => { draggable.classList.add('dragging') }) draggable.addEventListener('dragend', () => { draggable.classList.remove('dragging') }) } draggables.forEach(initDraggable) containers.forEach(container => { container.addEventListener('dragover', e => { e.preventDefault() const afterElement = getDragAfterElement(container, e.clientY) const draggable = document.querySelector('.dragging') if (afterElement == null) { container.appendChild(draggable) } else { container.insertBefore(draggable, afterElement) } }) }) function getDragAfterElement(container, y) { const draggableElements = [...container.querySelectorAll('.draggable: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 } </script> <!-- add new button --> <script src="http://code.jquery.com/jquery-1.8.1.min.js"></script> <script> $(document).ready(function() { $("#generatehtml").click(function() { const newDraggable = $($("#ambtnhtml").val()) initDraggable(newDraggable.get(0)) $(".pipp").append(newDraggable); $("ambtnhtml").val(""); }); }); </script> </html>