Есть очень тривиальный код, который работает как и ожидается:
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<style type="text/css">
.opacity {
opacity: 0;
}
</style>
</head>
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<div id="move" style="transition-duration: 1s;">4</div>
<script>
$(document).ready(function() {
function on_transitionend(event) {
$(this).toggleClass('opacity');
}
$('div').on('transitionend webkitTransitionEnd oTransitionEnd', on_transitionend);
$('#move').toggleClass('opacity');
});
</script>
</body>
</html>
Но, если в обработчике on_transitionend() осуществить перестановку элемента, то его свойство transition-duration перестает работать, соответственно, не происходит и вызов обработчика:
function on_transitionend(event) {
$(this).insertBefore($('div').get(0));
$(this).toggleClass('opacity');
}
При этом, в браузере видно, что все свойства и обработчики элемента, который был перестановлен на месте.
Если же после перестановки элемента попытаться вызвать обработчик transitionend не из основного потока а через setTimeout, то все работает как и ожидается:
function on_transitionend(event) {
$(this).insertBefore($('div').get(0));
var el = this
setTimeout(function() {$(el).toggleClass('opacity');}, 0);
}
Соответственно вопрос, почему так происходит и что именно происходит после изменения DOM дерева?
У меня есть лишь одна гипотеза: при изменении DOM дерева срабатывает апишное событие, которые помещается в очередь событий с наивысшим приоритетом. Соответственно, после завершения основного потока оно срабатывает и производит некий "ремаппинг" всего DOM дерева, включая обработчики и свойства. После этого нулевой таймаут срабатывает и все ОК. Если так, то можно ли вызвать этот "ремаппинг" вызвать из js кода?
Заранее большое спасибо за пояснения!