принудительное перерисовывание DOM с помощью javascript по требованию
название вопроса выражает то, что я думаю, является окончательным вопросом, стоящим за моим конкретным случаем.
моем случае: Внутри обработчика щелчков я хочу сделать изображение видимым (анимация "загрузки") прямо перед запуском функции занятости. Затем я хочу сделать его невидимым снова после завершения функции. Вместо того, что я ожидал, я понимаю, что изображение никогда не становится видимым. Я предполагаю, что это связано с браузером, ожидающим завершения обработчика, прежде чем он сможет сделать что-либо перерисовка (я уверен, что для этого есть хорошие причины).
код (также в этой скрипке: http://jsfiddle.net/JLmh4/2/)
HTML-код:
<img id="kitty" src="http://placekitten.com/50/50" style="display:none">
<div><a href="#" id="enlace">click to see the cat</a> </div>
js:
$(document).ready(function(){
$('#enlace').click(function(){
var kitty = $('#kitty');
kitty.css('display','block');
// see: http://unixpapa.com/js/sleep.html
function sleepStupidly(usec)
{
var endtime= new Date().getTime() + usec;
while (new Date().getTime() < endtime)
;
}
// simulates bussy proccess, calling some function...
sleepStupidly(4000);
// when this triggers the img style do refresh!
// but not before
alert('now you do see it');
kitty.css('display','none');
});
});
я добавил alert
звонок сразу после sleepStupidly
функция, чтобы показать, что в этот момент отдыха браузер перерисовывается, но не раньше. Я невинно ожидал, что он перерисует сразу после установки "display" на "block";
для record, я также попытался добавить теги html или поменять местами классы css вместо изображения, отображаемого и скрываемого в этом коде. Результат тот же.
после всех моих исследований я думаю, что то, что мне нужно, это возможность заставить браузер перерисовывать и прекратить все остальное до тех пор.
возможно ли это? Возможно ли это в crossbrowser? Некоторые плагин я не смог найти может...?
я подумал, что, может быть, что-то вроде ' jQuery css callback' (как в этом вопросе:в JQuery можно ли получить функцию обратного вызова после установки нового правила css?) будет делать трюк ... но этого не существует.
Я также попытался разделить показ, вызов функции и скрытие в разных обработчиках для одного и того же события ... но ничего. Также добавление setTimeout
для задержки выполнения функции (как рекомендуется здесь:принудительное обновление DOM в JavaScript).
спасибо и я надеюсь, что это также помогать другим.
Хавьера
EDIT (после установки моего предпочтительного ответа):
просто чтобы объяснить, почему я выбрал окно.стратегии через setTimeout. В моем реальном случае использования я понял, что для того, чтобы дать браузеру достаточно времени, чтобы перерисовать страницу, Я должен был дать ей около 1000 миллисекунд (гораздо больше, чем 50 для примера скрипки). Я считаю, что это связано с более глубоким деревом DOM (на самом деле, излишне глубоким). В функции setTimeout давайте подхода позволяет тебе это делать.
5 ответов
использовать window.setTimeout()
С некоторой короткой незаметной задержкой для запуска медленной функции:
$(document).ready(function() {
$('#enlace').click(function() {
showImage();
window.setTimeout(function() {
sleepStupidly(4000);
alert('now you do see it');
hideImage();
}, 50);
});
});
Использовать JQuery show
и hide
обратные вызовы (или другой способ отображения чего-то вроде fadeIn/fadeOut).
$(document).ready(function () {
$('#enlace').click(function () {
var kitty = $('#kitty');
// see: http://unixpapa.com/js/sleep.html
function sleepStupidly(usec) {
var endtime = new Date().getTime() + usec;
while (new Date().getTime() < endtime);
}
kitty.show(function () {
// simulates bussy proccess, calling some function...
sleepStupidly(4000);
// when this triggers the img style do refresh!
// but not before
alert('now you do see it');
kitty.hide();
});
});
});
чтобы принудительно перерисовать, вы можете использовать offsetHeight или getComputedStyle().
var foo = window.getComputedStyle(el, null);
или
var bar = el.offsetHeight;
" el " является элементом DOM
Я не знаю, работает ли это в вашем случае (поскольку я его не тестировал), но при манипулировании CSS с JavaScript/jQuery иногда необходимо принудительно перерисовывать определенный элемент, чтобы изменения вступили в силу.
это делается путем простого запроса свойства CSS.
в вашем случае, я бы попробовал поставить kitty.position().left;
перед вызовом функции до возни с setTimeout
.
то, что сработало для меня, устанавливает следующее:
$(element).css('display','none');
после этого вы можете делать все, что захочешь, и в конечном итоге вы хотите сделать:
$(element).css('display','block');