Как написать логику для TagBar?

430
31 января 2017, 22:22

Здравствуйте! Имеется следующая конструкция:

  • модальное окно popup-window со списком категорий (появляется при нажатии на add-category);
  • categories-list - блок, куда помещаются выбранные категории.

Логика такова: человек жмет на кнопку Add Category, появляется модальное окно - здесь выбираются нужные категории, жмется Choose и отмеченные выбранными категории появляются в поле блока categories-list. У каждой категории блока categories-list есть кнопка "удалить" - т.е. нажав на неё, категория исчезает и :checked в модалке снимается.

Большая просьба объяснить, как это сделать, ибо jQuery у меня на уровне addClass / removeClass.

Песочница

$('.categories-list .add-category').click(function () { 
  if ($('#select-category-popup').css('display') == 'none') { 
    $('#select-category-popup').fadeIn(); 
  } 
}); 
$('.close-modal-window').click(function () { 
  $('#select-category-popup').fadeOut(); 
}); 
$('.choose-btn').click(function() { 
  $('#select-category-popup').fadeOut(); 
})
.categories-list { 
  padding: 10px 20px 0 20px; 
  border-bottom: none; 
  list-style: none; 
  font-size: 0; 
  line-height: 0; 
  border: 1px solid #333; 
} 
.categories-list .category { 
  display: inline-block; 
  margin: 0 10px 10px 0; 
  position: relative; 
  border: 1px solid transparent; 
  padding: 6px 32px 4px 10px; 
  font-size: 14px; 
  line-height: 14px; 
  border-radius: 4px; 
  cursor: pointer; 
  -moz-transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
  -o-transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
  -webkit-transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
  transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
} 
.categories-list .category.selected-category { 
    background: #eeeeee; 
} 
.categories-list .category .category-icon { 
    position: absolute; 
    top: 0; 
    right: 0; 
    bottom: 0; 
    width: 32px; 
} 
.categories-list .category .category-icon:after { 
    content: ''; 
    font-family: 'FontAwesome'; 
    font-size: 16px; 
    position: absolute; 
    top: 0; 
    left: 0; 
    right: 0; 
    bottom: 0; 
    display: flex; 
    align-items: center; 
    justify-content: center; 
    -moz-transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
    -o-transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
    -webkit-transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
    transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
} 
.categories-list .category .category-icon.delete:after { 
    content: '\f00d'; 
    padding-bottom: 1px; 
    color: #aaa; 
} 
.categories-list .category .category-icon.add:after { 
    content: '\f067'; 
    padding-top: 1px; 
    color: #000; 
} 
.categories-list .category.add-category { 
    background: #ffe69a; 
} 
.categories-list .category:hover { 
    box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.1); 
} 
.categories-list .category.add-category:hover { 
    border: 1px solid #fbbc25; 
} 
.categories-list .category.selected-category:hover { 
    border: 1px solid #aaa; 
    background: #eeeeee; 
} 
.categories-list .category.selected-category:hover:after { 
} 
.categories-list .category .category-icon.delete:hover:after { 
    color: #333; 
} 
 
 
.category-list { 
  list-style: none; 
  margin: 0; 
  padding: 0; 
} 
#select-category-popup { 
  position: relative; 
  display: none; 
  width: 200px; 
  margin: 30px auto; 
  box-shadow: 0 0 10px 0 rgba(0,0,0,.5); 
  padding: 20px; 
} 
#select-category-popup .close-modal-window { 
  position: absolute; 
  top: 20px; 
  right: 20px; 
  cursor: pointer; 
} 
 
 
.choose-btn { 
  width: 100%; 
  margin-top: 20px; 
  cursor: pointer; 
  display: inline-block; 
  text-align: center; 
  color: red; 
}
<script src="https://use.fontawesome.com/ea0959dcb8.js"></script> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
<ul class="categories-list"> 
  <li class="category selected-category"> 
    Action 
    <span class="category-icon delete"></span> 
  </li> 
  <li class="category add-category"> 
    Add category 
    <span class="category-icon add"></span> 
  </li> 
</ul> 
 
<div id="select-category-popup" class="popup-window"> 
  <a class="close-modal-window"> 
    <i class="fa fa-times" aria-hidden="true"></i> 
  </a> 
  <div class="select-block--container"> 
    <ul class="category-list"> 
      <li class="category-item"> 
        <input id="category-action" type="checkbox"> 
        <label for="category-action">Action</label> 
      </li> 
      <li class="category-item"> 
        <input id="category-adventure" type="checkbox"> 
        <label for="category-adventure">Adventure</label> 
      </li> 
      <li class="category-item"> 
        <input id="category-card" type="checkbox"> 
        <label for="category-card">Card</label> 
      </li> 
    </ul> 
     
    <span class="choose-btn">Choose</span> 
  </div> 
</div>

Answer 1

На Вашем коде, специально на чистом js и как можно понятнее -

const tagList = document.body.querySelector('.categories-list'); 
 
const showSelectionTagFormButton = tagList.querySelector('.add-category'); 
showSelectionTagFormButton.addEventListener('click', showSelectionTagFormButton_clickHandler); 
 
const createTagButton = document.body.querySelector('.choose-btn'); 
createTagButton.addEventListener('click', createTagButton_clickHandler); 
 
function render(template){ 
	let element = document.createElement('div'); 
 
	element.innerHTML = template; 
 
	let result = element.removeChild(element.firstChild); 
 
	return result; 
} 
 
const Template = { 
	tag({title}){ 
		return (` 
			<li class="category selected-category"> 
				${ title } 
				<span class="category-icon delete"></span> 
				</li> 
		`).trim(); 
	} 
} 
function create(data){ 
	let template = Template.tag(data); 
	let tag = render(template); 
 
	initialization(tag); 
 
	tagList.insertBefore(tag, tagList.firstChild); 
 
	return tag; 
} 
function destroy(tag){ 
	uninitialization(tag); 
 
	tagList.removeChild(tag); 
} 
 
function initialization(tag){ 
	tag.addEventListener('click', tag_clickHandler); 
} 
function uninitialization(tag){ 
	tag.removeEventListener('click', tag_clickHandler); 
} 
 
function fill( data ){ 
	for(let currentData of data){ 
		let tag = create( currentData ); 
	} 
} 
function clear(){ 
	let tags = tagList.querySelectorAll('.selected-category'); 
 
	for(tag of tags){ 
		destroy(tag); 
	} 
} 
 
function getCheckboxData(checkboxs){ 
	let data = []; 
 
	for(let checkbox of checkboxs){ 
		data.push({ 
			title: checkbox.dataset.title 
		}) 
	} 
 
	return data; 
} 
 
function showSelectionTagForm(){ 
	document.body.querySelector('#select-category-popup').style.display = "block"; 
	document.body.querySelector('.fa-times').addEventListener('click',hideSelectionTagFormButton_clickHandler); 
} 
function hideSelectionTagForm(){ 
	document.body.querySelector('#select-category-popup').style.display = "none"; 
	document.body.querySelector('.fa-times').removeEventListener('click',hideSelectionTagFormButton_clickHandler); 
} 
 
 
function showSelectionTagFormButton_clickHandler(event){ 
	showSelectionTagForm(); 
} 
 
function hideSelectionTagFormButton_clickHandler(event){ 
	hideSelectionTagForm(); 
} 
 
function createTagButton_clickHandler(event){ 
	let categoryList = document.body.querySelector('.category-list'); 
	let checkboxs = categoryList.querySelectorAll('input[type="checkbox"]:checked'); 
 
	let data = getCheckboxData(checkboxs) 
		.sort( ( a, b ) => a.title - b.title ) 
		.reverse(); 
 
	clear(); 
	fill(data); 
 
	hideSelectionTagForm(); 
} 
 
function tag_clickHandler({target, currentTarget}){ 
	if(target.classList.contains('delete')){ 
		destroy(currentTarget); 
	} 
}
.categories-list { 
  padding: 10px 20px 0 20px; 
  border-bottom: none; 
  list-style: none; 
  font-size: 0; 
  line-height: 0; 
  border: 1px solid #333; 
} 
.categories-list .category { 
  display: inline-block; 
  margin: 0 10px 10px 0; 
  position: relative; 
  border: 1px solid transparent; 
  padding: 6px 32px 4px 10px; 
  font-size: 14px; 
  line-height: 14px; 
  border-radius: 4px; 
  cursor: pointer; 
  -moz-transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
  -o-transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
  -webkit-transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
  transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
} 
.categories-list .category.selected-category { 
  background: #eeeeee; 
} 
.categories-list .category .category-icon { 
  position: absolute; 
  top: 0; 
  right: 0; 
  bottom: 0; 
  width: 32px; 
} 
.categories-list .category .category-icon:after { 
  content: ''; 
  font-family: 'FontAwesome'; 
  font-size: 16px; 
  position: absolute; 
  top: 0; 
  left: 0; 
  right: 0; 
  bottom: 0; 
  display: flex; 
  align-items: center; 
  justify-content: center; 
  -moz-transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
  -o-transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
  -webkit-transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
  transition: all 0.4s cubic-bezier(0.2, 0.57, 0.36, 0.8); 
} 
.categories-list .category .category-icon.delete:after { 
  content: '\f00d'; 
  padding-bottom: 1px; 
  color: #aaa; 
} 
.categories-list .category .category-icon.add:after { 
  content: '\f067'; 
  padding-top: 1px; 
  color: #000; 
} 
.categories-list .category.add-category { 
  background: #ffe69a; 
} 
.categories-list .category:hover { 
  box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.1); 
} 
.categories-list .category.add-category:hover { 
  border: 1px solid #fbbc25; 
} 
.categories-list .category.selected-category:hover { 
  border: 1px solid #aaa; 
  background: #eeeeee; 
} 
.categories-list .category.selected-category:hover:after {} .categories-list .category .category-icon.delete:hover:after { 
  color: #333; 
} 
.category-list { 
  list-style: none; 
  margin: 0; 
  padding: 0; 
} 
#select-category-popup { 
  position: relative; 
  display: none; 
  width: 200px; 
  margin: 30px auto; 
  box-shadow: 0 0 10px 0 rgba(0, 0, 0, .5); 
  padding: 20px; 
} 
#select-category-popup .close-modal-window { 
  position: absolute; 
  top: 20px; 
  right: 20px; 
  cursor: pointer; 
} 
.choose-btn { 
  width: 100%; 
  margin-top: 20px; 
  cursor: pointer; 
  display: inline-block; 
  text-align: center; 
  color: red; 
}
<script src="https://use.fontawesome.com/ea0959dcb8.js"></script> 
<ul class="categories-list"> 
  <li class="category add-category"> 
    Add category 
    <span class="category-icon add"></span> 
  </li> 
</ul> 
 
<div id="select-category-popup" class="popup-window"> 
  <a class="close-modal-window"> 
    <i class="fa fa-times" aria-hidden="true"></i> 
  </a> 
  <div class="select-block--container"> 
    <ul class="category-list"> 
      <li class="category-item"> 
        <input id="category-action" type="checkbox" data-title="Action"> 
        <label for="category-action">Action</label> 
      </li> 
      <li class="category-item"> 
        <input id="category-adventure" type="checkbox" data-title="Adventure"> 
        <label for="category-adventure">Adventure</label> 
      </li> 
      <li class="category-item"> 
        <input id="category-card" type="checkbox" data-title="Card"> 
        <label for="category-card">Card</label> 
      </li> 
    </ul> 
 
    <span class="choose-btn">Choose</span> 
  </div> 
</div>

READ ALSO
Динамическая компоновка программы

Динамическая компоновка программы

Как скомпоновать программу на C++ c динамической библиотекой таким образом, чтобы основной исполняемый файл созданной программы мог находить...

323
BIOS, системные прерывания. int 11h, int 12h в С++ / C

BIOS, системные прерывания. int 11h, int 12h в С++ / C

Стоит задача получить информацию о компьютере, используя системное прерывание int 11h, которое записывает в регистр AX слово состояния (конфигурации)Доступ...

576
Ошибка в программе на C++

Ошибка в программе на C++

Помогите найти ошибку в коде, в ходе выполнения программы счётчик n=0, хотя у меня в блокноте есть такая запись "Ivanov Vasya 900-90-90"Суть программы:...

380
Является ли функция функтором

Является ли функция функтором

Является ли функция функтором?

391