Как правильно добавлять новую DOM Node?

119
27 ноября 2020, 21:20

Вырезал пример из моего проекта и сильно упростил: Данный код создаст один нужный мне фрагмент. Дело в том, что я хочу создавать неограниченное количество фрагментов и каждый раз создавать НОВУЮ колонку и работать с ней. Эдакой канбан. Ошибка в том что будет копироваться абсолютно всё: значения input, textarea и так далее. Как правильно реализовать решение? Гуглил Shadow DOM, и пробовал использовать но в итоге не понятно какой подход правильный. з.ы. Делаю нативно, без React.

const deskWrapper = document.querySelector('.deskWrapper'); 
const addButton = document.querySelector('.js-add-card'); 
 
 
 
const addNewDesk = () => { 
  const fragment = document.createDocumentFragment(); 
  const taskDeskItem = document.querySelector('.taskDesk'); 
  const newDesk = taskDeskItem.cloneNode(true); 
   
  fragment.appendChild(newDesk); 
  deskWrapper.appendChild(fragment); 
  addListeners() 
   
}; 
 
const addListeners = () => { 
   const newLastDesk = deskWrapper.children[deskWrapper.children.length - 1]; // ищем новую доску через родителя 
   newLastDesk.addEventListener('click', addNewDesk); 
} 
  
  
  
 
 addButton.addEventListener('click', addNewDesk)
.deskWrapper { 
  background: url("../img/deskWrapper/background.jpg") no-repeat center; 
  background-size: cover; 
  height: 100vh; 
  padding: 21px 20px; 
  display: flex; 
  flex-direction: row; 
  justify-content: flex-start; 
  align-items: flex-start; } 
 
.taskDesk { 
  display: block; 
  width: 150px; 
  min-height: 43px; 
  max-height: 614px; 
  background: #DFE3E6; 
  border-radius: 3px; 
  position: relative; 
  overflow: auto; 
  margin-right: 12px; } 
 
.taskDesk_box { 
  padding: 8px 12px; 
  width: 100%; 
  height: 100%; 
  display: flex; 
  flex-direction: column; 
  align-items: flex-start; 
  justify-content: flex-start; 
  flex-wrap: nowrap; } 
 
.taskDesk_title { 
  display: block; 
  font-weight: bold; 
  font-size: 13px; 
  line-height: 19px; 
  margin-bottom: 12px; } 
  .taskDesk_title .inactive { 
    display: none; } 
 
.task_list { 
  display: flex; 
  flex-direction: column; 
  flex-wrap: nowrap; 
  align-items: flex-start; 
  justify-content: flex-start; 
  width: 100%; 
  height: 100%; 
  overflow: auto; } 
 
.task_item { 
  background: #fff; 
  box-shadow: 0px 1px 4px rgba(9, 45, 66, 0.25); 
  border-radius: 3px; 
  width: 100%; 
  padding: 8px 12px; 
  margin-bottom: 8px; 
  font-size: 13px; 
  line-height: 19px; 
  font-family: "Montserrat", Helvetica, Arial, sans-serif; 
  word-wrap: break-word; } 
 
.taskDesk_add_box { 
  width: 100%; 
  background: #DFE3E6; 
  border-radius: 3px; 
  position: relative; } 
  .taskDesk_add_box.active .taskDesk_area { 
    display: block; 
    height: auto; } 
  .taskDesk_add_box.active .taskDesk_button_save { 
    display: flex; } 
  .taskDesk_add_box.active .taskDesk_button_close { 
    opacity: 1; 
    z-index: 10; } 
  .taskDesk_add_box.active .add_task { 
    display: none; } 
  .taskDesk_add_box.emptyArea .taskDesk_button_save { 
    background-color: #bbb; 
    pointer-events: none; } 
  .taskDesk_add_box.addColumn .add_title { 
    display: block; } 
  .taskDesk_add_box.addColumn .add_task { 
    display: none; } 
  .taskDesk_add_box.addColumn .taskDesk_input.active { 
    display: block; } 
  .taskDesk_add_box.addColumn .taskDesk_save_title.active { 
    display: flex; } 
  .taskDesk_add_box .taskDesk_save_title.emptyInput { 
    background: #39C071; 
    pointer-events: auto; } 
 
.taskDesk_button_add { 
  display: flex; 
  align-items: center; 
  justify-content: flex-start; 
  color: #6B808C; 
  margin-bottom: 10px; 
  font-size: 13px; 
  line-height: 19px; 
  transition: all .3s ease; 
  cursor: pointer; } 
  .taskDesk_button_add:hover, .taskDesk_button_add:active, .taskDesk_button_add:focus { 
    color: #000; } 
  .taskDesk_button_add:before { 
    content: ''; 
    display: inline-block; 
    vertical-align: middle; 
    width: 15px; 
    height: 15px; 
    background: url("../img/taskDesk/add.svg") no-repeat center; 
    background-size: contain; 
    margin-right: 8px; } 
 
.taskDesk_area { 
  display: none; 
  font-size: 13px; 
  line-height: 19px; 
  resize: none; 
  width: 100%; 
  height: 0; 
  padding: 8px 12px; 
  box-shadow: 0px 1px 4px rgba(9, 45, 66, 0.25); 
  border-radius: 3px; 
  font-family: "Montserrat", Helvetica, Arial, sans-serif; 
  margin-bottom: 8px; 
  transition: all .3s ease; } 
 
.taskDesk_input { 
  display: none; 
  width: 100%; 
  padding: 4px 12px; 
  box-shadow: 0px 1px 4px rgba(9, 45, 66, 0.25); 
  border-radius: 3px; 
  font-family: "Montserrat", Helvetica, Arial, sans-serif; 
  border: none; 
  margin-bottom: 8px; } 
 
.taskDesk_button_save { 
  display: none; 
  align-items: center; 
  justify-content: center; 
  width: 152px; 
  height: 30px; 
  background: #39C071; 
  border-radius: 3px; 
  font-weight: bold; 
  font-size: 13px; 
  line-height: 19px; 
  color: #fff; 
  transition: all .2s ease; } 
  .taskDesk_button_save:hover, .taskDesk_button_save:active, .taskDesk_button_save:focus { 
    background: #45c04f; } 
 
.taskDesk_button_close { 
  width: 15px; 
  height: 15px; 
  display: inline-block; 
  position: absolute; 
  bottom: 9px; 
  right: 0; 
  background: url("../img/taskDesk/cross.svg") no-repeat center; 
  background-size: contain; 
  cursor: pointer; 
  opacity: 0; 
  z-index: -10; 
  transition: all 0s; } 
 
.add_title { 
  display: none; 
  margin-bottom: 8px; } 
 
.taskDesk_save_title { 
  display: none; 
  align-items: center; 
  justify-content: center; 
  width: 152px; 
  height: 30px; 
  border-radius: 3px; 
  font-weight: bold; 
  font-size: 13px; 
  line-height: 19px; 
  color: #fff; 
  transition: all .2s ease; 
  pointer-events: none; 
  background: #bbb; }
<section class="deskWrapper"> 
  <div class="taskDesk"> 
    <div class="taskDesk_box"> 
      <h3 class="taskDesk_title"></h3> 
      <ul class="task_list"> 
       
      </ul> 
      <form class="taskDesk_add_box emptyArea"> 
        <button class="taskDesk_button_add add_task js-add-card" type="button">Добавить еще одну карточку</button> 
        <input name="name"/> 
      </form> 
    </div> 
  </div> 
</section>

Answer 1

Так с самого начала скопируйте состояние доски и потом чистенькую вставляйте.

const deskWrapper = document.querySelector('.deskWrapper'); 
const addButton = document.querySelector('.js-add-card'); 
const newDesk = (function(){ 
    const taskDeskItem = document.querySelector('.taskDesk').cloneNode(true); 
    return function(){ 
        return taskDeskItem.cloneNode(true); 
        } 
    })(); 
 
 
const addNewDesk = () => { 
  const fragment = document.createDocumentFragment(); 
 
  fragment.appendChild(newDesk()); 
  deskWrapper.appendChild(fragment); 
  addListeners() 
   
}; 
 
const addListeners = () => { 
   const newLastDesk = deskWrapper.children[deskWrapper.children.length - 1].getElementsByTagName('button')[0]; // ищем новую доску через родителя 
   newLastDesk.addEventListener('click', addNewDesk); 
} 
  
  
  
 
 addButton.addEventListener('click', addNewDesk)
.deskWrapper { 
  background: url("../img/deskWrapper/background.jpg") no-repeat center; 
  background-size: cover; 
  height: 100vh; 
  padding: 21px 20px; 
  display: flex; 
  flex-direction: row; 
  justify-content: flex-start; 
  align-items: flex-start; } 
 
.taskDesk { 
  display: block; 
  width: 150px; 
  min-height: 43px; 
  max-height: 614px; 
  background: #DFE3E6; 
  border-radius: 3px; 
  position: relative; 
  overflow: auto; 
  margin-right: 12px; } 
 
.taskDesk_box { 
  padding: 8px 12px; 
  width: 100%; 
  height: 100%; 
  display: flex; 
  flex-direction: column; 
  align-items: flex-start; 
  justify-content: flex-start; 
  flex-wrap: nowrap; } 
 
.taskDesk_title { 
  display: block; 
  font-weight: bold; 
  font-size: 13px; 
  line-height: 19px; 
  margin-bottom: 12px; } 
  .taskDesk_title .inactive { 
    display: none; } 
 
.task_list { 
  display: flex; 
  flex-direction: column; 
  flex-wrap: nowrap; 
  align-items: flex-start; 
  justify-content: flex-start; 
  width: 100%; 
  height: 100%; 
  overflow: auto; } 
 
.task_item { 
  background: #fff; 
  box-shadow: 0px 1px 4px rgba(9, 45, 66, 0.25); 
  border-radius: 3px; 
  width: 100%; 
  padding: 8px 12px; 
  margin-bottom: 8px; 
  font-size: 13px; 
  line-height: 19px; 
  font-family: "Montserrat", Helvetica, Arial, sans-serif; 
  word-wrap: break-word; } 
 
.taskDesk_add_box { 
  width: 100%; 
  background: #DFE3E6; 
  border-radius: 3px; 
  position: relative; } 
  .taskDesk_add_box.active .taskDesk_area { 
    display: block; 
    height: auto; } 
  .taskDesk_add_box.active .taskDesk_button_save { 
    display: flex; } 
  .taskDesk_add_box.active .taskDesk_button_close { 
    opacity: 1; 
    z-index: 10; } 
  .taskDesk_add_box.active .add_task { 
    display: none; } 
  .taskDesk_add_box.emptyArea .taskDesk_button_save { 
    background-color: #bbb; 
    pointer-events: none; } 
  .taskDesk_add_box.addColumn .add_title { 
    display: block; } 
  .taskDesk_add_box.addColumn .add_task { 
    display: none; } 
  .taskDesk_add_box.addColumn .taskDesk_input.active { 
    display: block; } 
  .taskDesk_add_box.addColumn .taskDesk_save_title.active { 
    display: flex; } 
  .taskDesk_add_box .taskDesk_save_title.emptyInput { 
    background: #39C071; 
    pointer-events: auto; } 
 
.taskDesk_button_add { 
  display: flex; 
  align-items: center; 
  justify-content: flex-start; 
  color: #6B808C; 
  margin-bottom: 10px; 
  font-size: 13px; 
  line-height: 19px; 
  transition: all .3s ease; 
  cursor: pointer; } 
  .taskDesk_button_add:hover, .taskDesk_button_add:active, .taskDesk_button_add:focus { 
    color: #000; } 
  .taskDesk_button_add:before { 
    content: ''; 
    display: inline-block; 
    vertical-align: middle; 
    width: 15px; 
    height: 15px; 
    background: url("../img/taskDesk/add.svg") no-repeat center; 
    background-size: contain; 
    margin-right: 8px; } 
 
.taskDesk_area { 
  display: none; 
  font-size: 13px; 
  line-height: 19px; 
  resize: none; 
  width: 100%; 
  height: 0; 
  padding: 8px 12px; 
  box-shadow: 0px 1px 4px rgba(9, 45, 66, 0.25); 
  border-radius: 3px; 
  font-family: "Montserrat", Helvetica, Arial, sans-serif; 
  margin-bottom: 8px; 
  transition: all .3s ease; } 
 
.taskDesk_input { 
  display: none; 
  width: 100%; 
  padding: 4px 12px; 
  box-shadow: 0px 1px 4px rgba(9, 45, 66, 0.25); 
  border-radius: 3px; 
  font-family: "Montserrat", Helvetica, Arial, sans-serif; 
  border: none; 
  margin-bottom: 8px; } 
 
.taskDesk_button_save { 
  display: none; 
  align-items: center; 
  justify-content: center; 
  width: 152px; 
  height: 30px; 
  background: #39C071; 
  border-radius: 3px; 
  font-weight: bold; 
  font-size: 13px; 
  line-height: 19px; 
  color: #fff; 
  transition: all .2s ease; } 
  .taskDesk_button_save:hover, .taskDesk_button_save:active, .taskDesk_button_save:focus { 
    background: #45c04f; } 
 
.taskDesk_button_close { 
  width: 15px; 
  height: 15px; 
  display: inline-block; 
  position: absolute; 
  bottom: 9px; 
  right: 0; 
  background: url("../img/taskDesk/cross.svg") no-repeat center; 
  background-size: contain; 
  cursor: pointer; 
  opacity: 0; 
  z-index: -10; 
  transition: all 0s; } 
 
.add_title { 
  display: none; 
  margin-bottom: 8px; } 
 
.taskDesk_save_title { 
  display: none; 
  align-items: center; 
  justify-content: center; 
  width: 152px; 
  height: 30px; 
  border-radius: 3px; 
  font-weight: bold; 
  font-size: 13px; 
  line-height: 19px; 
  color: #fff; 
  transition: all .2s ease; 
  pointer-events: none; 
  background: #bbb; }
<section class="deskWrapper"> 
  <div class="taskDesk"> 
    <div class="taskDesk_box"> 
      <h3 class="taskDesk_title"></h3> 
      <ul class="task_list"> 
       
      </ul> 
      <form class="taskDesk_add_box emptyArea"> 
        <button class="taskDesk_button_add add_task js-add-card" type="button">Добавить еще одну карточку</button> 
        <input name="name"/> 
      </form> 
    </div> 
  </div> 
</section>

READ ALSO
&ldquo;баг&rdquo; с сортировкой односвязного списка с++

“баг” с сортировкой односвязного списка с++

нужно отсортировать односвязный список по одному из информационных полей(в моем случае kol), написал вот такую функцию, но проблема в том, что...

111
явная специализация шаблонов C++

явная специализация шаблонов C++

При объявлении шаблонной функции с явной специализацией для строки( тип char*) появляется ошибка “отсутствуют экземпляры шаблон функции”

224
QT: repaint() не перерисовывает виджет

QT: repaint() не перерисовывает виджет

По ТЗ необходимо реализовать построчную закраску многоугольника в двух вариантах - с задержкой после отрисовки каждой линии и без нееЕсть...

115