Предыстория
Извините за столь простой и возможно "глупый" вопрос, однако я немного путаюсь в тоннах информации в сети и чтобы не перечитывать всё прошу у вас подсказку.
Мне необходимо попрактиковаться (а откровенно говоря научиться) работать с элементами свёрстанного макета, и для этого необходимо знать о чём именно читать и собственно какие методы использовать. И конечно я буду делать это последовательно и детально, однако сейчас есть небольшая задача которую нужно решить.
Задача заключается в том, что необходимо сделать след. страничку - клик
своими силами на чистом JS, как получится главное чтобы было похоже и был такой же функционал. Вопрос мой в том, что мне необходим список нужных методов с которыми я буду учиться взаимодействовать. Для индикации элемента я уже использую document.getElementById('id').value.trim()
трим чтобы исключить пробелы (ну вы и так знаете), далее я умею создавать функцию по клику на кнопку или мышку, и выводить захваченный текст с помощью document.getElementById('id').innerHTML = text
.
Вопросы
В моей вёрстке я создал инпут с вводом и под ним список, сделал кнопку закрытия фонтассомом и скрыл элемент списка (мой template).
Мне нужны методы, которые позволят:
1) клонировать мой шаблон списка;
2) выставлять этого клона с добавлением класса (в кот. будет убран display:none
) и кратко как это делается;
3) метод удаления этих Li-шек (которые будут добавлены при вводе информации в инпут).
Большое спасибо!
Здесь минимальный рабочий пример (с мелкими косяками), но я сильно не заморачивался с точностью. Вам придется еще сверху много чего добавить. Поэтому этот код годится только на "подсмотреть и написать своё с нуля".
( JsFiddle )
var check = document.querySelector('.check'); /*серая галочка слева от инпута*/
var firstClick = 1; /* в логическом контексте 1 == true, 0 == false */
check.addEventListener('click', function() {
var checkbox = document.querySelectorAll('.checkbox');
if (firstClick) { // Будет true
this.classList.add('active'); // this указывает на кликнутый элемент
for (var i = 0; i < checkbox.length; i++) {
checkbox[i].classList.add('active');
}
// При первом клике (когда до этого галки вручную могут быть через раз включены или нет)
// Добавляем активный класс на все чекбоксы без разбора
firstClick = 0;
} else {
// А на следующих кликах условие уже не выполнится - пойдет переключение.
this.classList.toggle('active');
for (var i = 0; i < checkbox.length; i++) {
checkbox[i].classList.toggle('active');
}
}
});
var todo = document.getElementById('todo-list');
var bubu = document.getElementById('bubu');
bubu.addEventListener('keydown', function(e) {
if (e.code == "Enter" && this.value.length) {
// Если this.value.length будет 0, это false
todo.insertAdjacentHTML('afterbegin', '<li class="li"><div class="checkbox"></div><div class="delete">X</div><div class="txt">' + this.value + '</div></li>');
this.value = "";
check.style.display = "block"; // Показываем серую галочку
firstClick = 1;
}
});
var prevClick; // Для хранения времени и отслеживания двойного клика
todo.addEventListener('click', function(e) {
var target = e.target; // Кликнутый элемент
if (target.className.match(/delete/)) {
target.parentNode.outerHTML = ""; // Удаляем родительский элемент (крестик лежал внутри него).
return; // return прерывает выполнение функции.
}
if (target.className.match(/checkbox/)) {
target.classList.toggle('active');
var act = document.querySelectorAll('.checkbox.active');
var chbx = document.querySelectorAll('.checkbox');
// Это уже мелкие заморочки. Проверка - если общее количество отмеченных
// Совпадает с кол-вом чекбоксов - делаем серую галочку темнее, иначе - светлее.
if( chbx.length === act.length ){
check.classList.add('active');
} else {
check.classList.remove('active');
}
firstClick = 1;
return;
}
var now = Date.now();
if ( target.className.match(/txt/) && ( now - prevClick < 1000)) { // Если от предыдущего клика прошло менее 1 сек.
// Существует и событие dblclick, но мне показалось так легче.
// Тем более, можно управлять скоростью двойного клика.
target.contentEditable = true;
// А еще показалось, что будет легче делать блок редактируемым, чем создавать в этом месте textarea
getSelection().collapseToEnd();
// Это чтобы от двойного клика текст не выделился и случайно не удалили нажатием кнопки.
target.focus();
}
prevClick = now;
});
document.addEventListener('click', function(e) {
if (e.target.contentEditable == "true") {
return;
}
var x = document.querySelector('.txt[contentEditable]');
if (x) {
x.removeAttribute('contentEditable');
// Для div нет разницы, какое там значение у contenteditable... если оно есть
// - будет работать. Значит нужно убрать именно атрибут.
}
});
.relative {
position: relative;
}
.bubu { /* Основной инпут */
font-size: 28px;
color: #222;
padding: 5px 5px 5px 40px;
outline: none;
width: 400px;
}
.bubu::placeholder {
color: #ddd;
font-style: italic;
}
.check { /* Блок для серой галочки слева от инпута */
display: none;
position: absolute;
top: 10px;
left: 10px;
width: 21px;
height: 20px;
overflow: hidden; /* Это чтобы галочка была обрезана с краев */
box-sizing: border-box;
line-height: 0;
}
.check::after { /* Сама галочка */
content: "";
position: absolute;
width: 20px;
height: 20px;
bottom: 5px;
left: -1px;
border-bottom: 3px solid #ccc;
border-right: 3px solid #ccc;
transform: rotate(45deg);
}
.check.active::after { /* делаем галку чуть темнее, когда добавлен активный класс */
border-color: #666;
}
#todo-list { /* Общий ul блок */
width: 445px;
padding: 0;
margin: 0;
}
.li {
position: relative; /* Это чтобы удержать внутренние абсолютные блоки
иначе они будут убегать за рамки li */
list-style: none;
margin: 0;
padding: 15px 0 15px 50px;
font-size: 24px;
font-family: 'Helvetica';
color: #333;
border-bottom: 1px solid #ccc;
cursor: default;
}
.checkbox { /* круглая серая рамка будущего чекбокса */
position: absolute;
border: 1px solid #ccc;
border-radius: 50%;
width: 24px;
height: 24px;
left: 10px;
top: 15px;
}
.checkbox::after { /* Скрытая галочка чекбокса */
display: none;
content: "";
position: absolute;
border-bottom: 2px solid #6aa;
border-right: 2px solid #6aa;
transform: rotate(30deg);
width: 5px;
height: 15px;
left: 8px;
top: 3px;
}
/* Показываем галочку и подкрашиваем рамку, когда он будет включен */
.checkbox.active::after {
display: block;
}
.checkbox.active {
border-color: #9cc;
}
.delete { /* Кнопки-крестики удаления */
position: absolute;
right: 10px;
top: 15px;
font-family: 'tahoma';
font-weight: 100;
color: #d40;
cursor: pointer;
}
div[contentEditable] {
padding: 13px 0;
margin: -13px 0;
box-shadow: 0 0 2px 2px #555;
outline: none;
position: relative;
z-index: 1;
background: white;
}
.checkbox.active ~ .txt {
text-decoration: line-through;
color: #aaa;
}
<div class="relative">
<input class="bubu" id="bubu" placeholder="What needs to be done?">
<div class="check"></div>
</div>
<ul id="todo-list"></ul>
P.s. можете еще поискать:
• Делегирование Событий
• Регулярные выражения... В целом - полезная штука. Хотя тут они использованы только в match, для определения, есть ли у элемента указанный класс. Это не лучший способ, но здесь прокатывает.
• matches(), closest()
• CSS-селекторы. Они активно используются в querySelector(...)
. У меня в коде все переключения-галочки написаны на div, но в вашей ссылке они сделаны через настоящие чекбоксы и label... Есть полезный селектор .class:checked
- находит именно отмеченный чекбокс с этим классом. Так, одной кнопкой скрывая или удаляя все отмеченные, в моём коде можно было достать их через
document.querySelectorAll('.checkbox.active');
или, для реальных чекбоксов:
document.querySelectorAll('.checkbox:checked');
Пройдите, например, вот эти уроки - http://code.mu/tasks/javascript/base/osnovy-yazyka-javascript-dlya-novichkov.html (там есть как практические задачи, так и теория). Думаю это даст Вам достаточно хороший базис.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Этот вопрос задавался не разНо возможно в конкретном случае его можно решить как-то иначе
Как новичку начать изучение Javascript, посоветуйте лучшие источники