动态创建的元素在 HTML 和 JS 中可拖动的问题

问题描述 投票:0回答:1

我正在帮助一位朋友为他们的一个班级设计一个班级组织者。我有一个类列表,显示在屏幕左侧的搜索栏上,需要将它们拖到屏幕右侧的框中。如果我手动将元素添加到 HTML,我用于可拖动项目的 JS 工作得很好,但是当我使用 JS 使用 CSV 文件中的数据添加元素时,它们无法拖动。我找到的唯一解决方案是我需要在创建项目的循环中读取拖动函数的侦听器,但这并没有解决我的问题。我已经添加了下面的 html js 和 css。除了 papaparse 之外,我没有使用任何库来提取 CSV 数据。

//dynamically add lines to search menu

var data;

Papa.parse('test.csv', {
 header: true,
 download: true,
 dynamicTyping: true,
 complete: function(results) {
   console.log(results);
   data = results.data;
   console.log(data.length);

   // Create and append draggable elements
   for(var i = 0; i < data.length; i++) {
     var opt = data[i].Title;
     var el = document.createElement("p");
     el.setAttribute("class","draggable");
     el.setAttribute("draggable","true");
     el.value = opt;
     el.textContent = opt;
     el.addEventListener('dragstart', () => {
      el.classList.add('dragging')
    })
  
    el.addEventListener('dragend', () => {
      el.classList.remove('dragging')
    })

    classitem.appendChild(el);
   }
 }
});

//allows elements to be draggable
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
}


    /* When the user clicks on the button,
    toggle between hiding and showing the dropdown content */
    function myFunction() {
      document.getElementById("myDropdown").classList.toggle("show");
    }
    
    function filterFunction() {
      var input, filter, ul, li, a, i;
      input = document.getElementById("myInput");
      filter = input.value.toUpperCase();
      div = document.getElementById("myDropdown");
      p = div.getElementsByTagName("p");
      for (i = 0; i < p.length; i++) {
        txtValue = p[i].textContent || p[i].innerText;
        if (txtValue.toUpperCase().indexOf(filter) > -1) {
          p[i].style.display = "";
        } else {
          p[i].style.display = "none";
        }
      }
    }

<!DOCTYPE html>
<html lang="en" >
<head> 
  <script  src="papaparse.min.js"></script>

  <meta charset="UTF-8">
  <title></title>
  <link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Merriweather|Open+Sans'><link rel="stylesheet" href="./haha.css">
  <style>
header {
  font-family: "Open Sans", sans-serif;
  font-size: 16px;
  font-weight: 100;
}

body {
  font-family: Merriweather, serif;
}
</style>
</head>
<body>
  <div class="header">
    <h1>test</h1>
  </div>
<p id="classdata"></p>
<p id="classdata2"></p>
<p style="height: 100px;"></p>
<h2 style="text-align: centre; position: relative; padding-left: 200px; padding-top: 0px; display:inline-block;">Courses</h2>
<h2 style="text-align: centre; position: relative; padding-left: 200px; padding-top: 0px; display:inline-block;">Four year plan</h2>
<div class="row">
  <div class="column">  
   <!--dropdown-->  
   <div class="dropdown">
    <button onclick="myFunction()" class="dropbtn">Core Classes</button>
    <div id="myDropdown" class="dropdown-content">
      <input type="text" placeholder="Search.." id="myInput" onkeyup="filterFunction()">
      <div id="classitem" class="container" style="width: 70%; background-color: white; border: none;">
        <p class="draggable" draggable="true">CHEM1000</p>
      </div>
    </div>
  </div> 
  </div>
  <div class="column2">   
  <div class="top">
    <div class="container">
    </div>
    <div class="container">
    </div>
    <div class="container">
    </div>
    <div class="container">
    </div>
  </div>
  <div class="bot">
    <div class="container">
    </div>
    <div class="container">
    </div>
    <div class="container">
    </div>
    <div class="container">
    </div>
  </div>       
  </div>
</div> 

<script src="./hehe.js"></script>

</body>
</html>

body {
  margin: 0;
}
.row {
  display: flex;
}
.header {
padding: 10px;
text-align: left;
background: #982828;
color: white;
letter-spacing: 16px;
font-weight: 100;
}

.column {
  flex: 20%;
}
.column2 {
  flex: 80%;
}
.container {
  background-color: white;
  border-radius: 10px;
  width: 20%;
  border: 1px solid black;
  height: 17rem;
  padding: .5rem;
  margin: .1rem;
  float:d left;
  overflow: auto;
}
.top {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
.bot {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
.draggable {
  margin-top: .5rem;
  padding: .4rem;
  border-radius: 10px;
  width: auto;
  background-color: white;
  border: 1px solid black;
  cursor: move;
}

/* ===== Scrollbar CSS ===== */
/* Firefox */
* {
  scrollbar-width: auto;
  scrollbar-color: #565252 #ffffff;
}

/* Chrome, Edge, and Safari */
*::-webkit-scrollbar {
  width: 14px;
  
}

*::-webkit-scrollbar-track {
  background: #ffffff;
}

*::-webkit-scrollbar-thumb {
  background-color: #565252;
  border-radius: 10px;
  border: 3px solid #ffffff;
}

.draggable.dragging {
  opacity: .5;
}


#myInput {
  box-sizing: border-box;
  background-image: url('searchicon.png');
  background-position: 14px 12px;
  background-repeat: no-repeat;
  position: relative;
  border-radius: 5px;
  width: 220px;
  font-size: 16px;
  padding: 14px 20px 12px 45px;
  border: 1px solid black;
}

#myInput:focus {outline: 3px solid #ddd;}

.dropdown {
  position: relative;
  left: 50%;
  margin-left: -150px;
  display: inline-block;
}
.dropbtn {
  display: inline-block;
  background-color: white;
  border: 1px solid black;
  color: black;
  padding: 16px;
  position: relative;
  margin-top: .1rem;

  font-size: 16px;
  border-radius: 5px;
  width: 300px;
  cursor: pointer;
}

.dropbtn:hover, .dropbtn:focus {
  background-color: white;
}

.dropdown-content {
  display: none;
  position: absolute;
  border-radius: 5px;
  background-color: white;
  margin: 24px 17px 24px 33px;
  min-width: 250px;
  z-index: 1;
}


.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

.dropdown a:hover {background-color: #ddd;}

.show {display: block;}
javascript html dynamic draggable
1个回答
0
投票

嗯,我明白了...您是否尝试过制作一个单独的 JS 文件来让元素可拖动?就像

hehe1.js
你的主要代码在哪里,
hehe2.js
用于拖动东西?或者,您用来读取 CSV 文件的库需要很长时间才能执行某个功能,因此请尝试编写如下代码:


function makeEmDragging(){
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
}
}

var data;

Papa.parse('test.csv', {
 header: true,
 download: true,
 dynamicTyping: true,
 complete: function(results) {
   console.log(results);
   data = results.data;
   console.log(data.length);

   // Create and append draggable elements
   for(var i = 0; i < data.length; i++) {
     var opt = data[i].Title;
     var el = document.createElement("p");
     el.setAttribute("class","draggable");
     el.setAttribute("draggable","true");
     el.value = opt;
     el.textContent = opt;
     el.addEventListener('dragstart', () => {
      el.classList.add('dragging')
    })
  
    el.addEventListener('dragend', () => {
      el.classList.remove('dragging')
    })

    classitem.appendChild(el);
makeEmDragging()
   }
 }
});

© www.soinside.com 2019 - 2024. All rights reserved.