Учусь javascript и на данном этапе пытаюсь разобраться с кастомными событиями, а так же их использованием в интерфейсах. Есть написанный мною скрипт, он ловит события на элементе контейнере. Если клик произошел по кнопке, то генерируется блок. Когда блок сгенирировался на нем срабатывает кастомное событие и всплывает до блока родителя, где оно отлавливается и запускается анимация. В данном случае это увеличение размеров блока до 100 пикселей в течение секунды. И вот по завершению анимации должно сработать кастомное событие, извещающее об окончании анимации на сгенирированном блоке и в этот блок должна быть добавлена картинка. Собственно сейчас получается, если раскомментировать код, что картинка сразу показывается. Подскажите как исправить.
http://plnkr.co/edit/qamVQqgeJxCHHElnfwYD?p=preview
<style>
.transformer-button {
background-image: linear-gradient(#cb72cb 0%, #a003a0 100%);
padding: 6px 10px;
border: none;
border-radius: 5px;
box-shadow: 2px 2px 6px #7d037d;
cursor: pointer;
color: #fff;
margin-bottom: 20px;
}
.shadow {
box-shadow: 1px 1px 4px #000;
}
.image-container {
background-color: #aaa;
width: 10px;
height: 10px;
}
.transformer-button:focus {
outline: none;
}
</style>
<div class="transformer" data-role="container">
<button class="transformer-button" data-role="opener">Magic Button</button>
</div>
'use strict'
class Transformer {
constructor(options) {
this._elem = options.elem;
this._elem.addEventListener('click', this._onClick.bind(this));
this._elem.addEventListener('appearance', this._onDivAppearance.bind(this));
/* this._elem.addEventListener('finishAnimation', this._onFinishAnimation.bind(this));*/
}
_onClick(event) {
let target = event.target;
let opener = target.closest('[data-role=opener]');
let image = this._elem.querySelector('[data-role=image]');
if (target != opener) return;
if (image) {
let box = this._elem.removeChild(image);
}
opener.addEventListener('mousedown', this._onOpenerMousedown.bind(this));
opener.addEventListener('mouseup', this._onOpenerMouseup.bind(this));
let div = document.createElement('div');
div.setAttribute('data-role', 'image');
/*div.classList.add('image-container');*/
div.style.width = '10px';
div.style.height = '10px';
div.style.backgroundColor = '#aaa';
this._elem.appendChild(div);
let appearance = new CustomEvent("appearance", {
bubbles: true
});
div.dispatchEvent(appearance);
}
_onDivAppearance(event) {
let target = event.target;
this._animate(this._draw.bind(this, target), 1000);
/* let finishAnimation = new CustomEvent("finishAnimation", {
bubbles: true
});
target.dispatchEvent(finishAnimation);*/
}
/* _onFinishAnimation(event) {
let imageContainer = event.target;
let image = document.createElement('img');
image.setAttribute('src', 'http://ava.prohatku.ru/media/image/200jpg/fox/0014.jpg');
imageContainer.appendChild(image);
}*/
_onOpenerMousedown(event) {
event.target.classList.add('shadow');
}
_onOpenerMouseup(event) {
event.target.classList.remove('shadow');
}
_animate(draw, duration) {
let start = performance.now();
requestAnimationFrame(function animate(time) {
// определить, сколько прошло времени с начала анимации
let timePassed = time - start;
// возможно небольшое превышение времени, в этом случае зафиксировать конец
if (timePassed > duration) timePassed = duration;
// нарисовать состояние анимации в момент timePassed
draw(timePassed);
// если время анимации не закончилось - запланировать ещё кадр
if (timePassed < duration) {
requestAnimationFrame(animate);
}
});
}
_draw(target, timePassed) {
target.style.width = timePassed / 5 + 'px';
target.style.height = timePassed / 5 + 'px';
}
}
let options = {
elem: document.querySelector('[data-role=container]')
}
let transformer = new Transformer(options);