Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 18.08.2011, 10:24
Аспирант
Отправить личное сообщение для RUVATA Посмотреть профиль Найти все сообщения от RUVATA
 
Регистрация: 08.02.2011
Сообщений: 41

Принудительный рендеринг, отрисовка, redraw, reflow ; во время работы с COM(ActiveX)
Всем доброго времени суток...
Проблема истрепала кучу нервов и времени, потому хочу поделиться соображениями, частичным решением, найденным материалом, дабы столкнувшиеся не корячились как я.

Все началось с того, что клиентской части внутреннего сайта понадобилась работа с Excel на конечном компе юзверя, подумав, почитав, решили в пользу IE + ActiveX, а для филиалов не имеющих доступ к внутреннему сайту передать сие творение в виде *.hta (HTML Application) (типо убиваем двух зайцев )
(тем более прецедент уже есть - система "Контур Экстерн" которая только в IE и работатет)

Ну вот и понеслась... логику отработали быстро, опыт COM-взаимодействия с Excel благо богатый, с JavaScript тоже проблем не имеем.
Вот казалось бы и все, логика выполняется верно на связках:
WinXP+IE8, Win7+IE8, Win7+IE9 (как в виде страницы сайта с разрешения юзверя, так и в виде *.hta приложения)
Расчеты, чтение/заполнение таблиц, работа с файловой системой занимают от 5-6 до 15-20 сек, так что было решено анимировать процесс, дабы было видно что идет обработка. И тут началось...
Пошли по классическому пути через setTimeout, setInterval, после нескольких неудач решили особо не мудрить - разбили логику на несколько последовательных функций, между которыми и будет происходить некая анимация - изменяться текст в
<textarea id='satus'>Здесь будет статус выполнения</textarea>

модель такая:
myAnimation('выполняется myFunction1')
myFunction1()
    myAnimation('выполняется myFunction2')
myFunction2()
    myAnimation('выполняется myFunction3')
myFunction3()
    myAnimation('выполняется myFunction4')
myFunction4()
    myAnimation('выполняется myFunction5')
myFunction5()
    myAnimation('выполняется myFunction6')
myFunction6()
    myAnimation('Готово')

function myAnimation(text){
var element = document.getElementById("status");	
element.value = text
};

и что вы думаете ?
все myFunction*() успешно выполняются одна за одной... а вот в 'satus' отрисовывается только 'выполняется myFunction1'... и висит, потом когда все расчеты закончатся быстро мелькает 'выполняется myFunction6' и 'Готово'
Часы "гугления", с десяток постов на разных форумах, все без толку.
Вроде все должно работать... а не не работает.
Так вот ИСТИНА !!! :
Это особенность "осла", как только осел начинает работать с COM-компонентами, он в целях повышения производительности
вырубает весь автоматический рендеринг(обоход DOM мол слишком дорогое удовольствие во время работы с COM), и пока объект "захвачен" без пинка ничего отрисовывать не станет...
как же дать ему "пинка"!
вот здесь, представлен такой список свойств елемента, обращение к которым вызовет принудительный reflow&redraw:
Цитата:
1. offsetTop, offsetLeft, offsetWidth, offsetHeight,
2. scrollTop/Left/Width/Height,
3. clientTop/Left/Width/Height,
4. getComputedStyle() или currentStyle в IE.
так вот... в нашем случае (работа с COM) currentStyle, который Вам везде будут советовать и к нему Вас приведет гугление - НЕ СРАБОТАЕТ НИ В ОДНОМ IE!!!
В IE8, IE9 (в виде html, на XP или Win7, и только на Win7 в виде *.hta) - нам помогут свойства и 1-го пункта
т.е. изменив функцию таким образом:
function myAnimation(text){
var element = document.getElementById("status");	
element.value = text
element.offsetHeight
};

мы добьёмся анимации...
для *.hta в WinXP даже такой трюк не срабатывает
хотя здесь представлено несколько иных способов, в том числе и среди коментов предлагают
Цитата:
I use the following:

elm.style.display=”none”;
var redrawFix = elm.offsetHeight;
elm.style.display=”block”; // or other value if required

This works in all browsers I have needed it for – Opera, Konqueror, Safari and IE (including IE8 RC1 for which I just needed a redraw fix too). I haven’t ever needed it for Firefox though..
ни один не работает для *.hta на WinXP... для этой связки я так и не нашел решения.
Ответить с цитированием
  #2 (permalink)  
Старый 18.08.2011, 10:48
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Сообщение от RUVATA
пока объект "захвачен"
а что это значит?
Ответить с цитированием
  #3 (permalink)  
Старый 18.08.2011, 11:01
Аватар для Magneto
Люмус, Емаксос Developer!
Отправить личное сообщение для Magneto Посмотреть профиль Найти все сообщения от Magneto
 
Регистрация: 06.05.2010
Сообщений: 677

Если я не ошибаюсь, в качестве движка для HTA-приложений используется в XP IE6 в Win7 IE7, независимо от того какой браузер установлен в системе.

Для визуализации попробуйте использовать GIF-анимацию, вначале выводите гифку, загружаете все что нужно, удаляете гифку.
Ответить с цитированием
  #4 (permalink)  
Старый 18.08.2011, 11:35
Аспирант
Отправить личное сообщение для RUVATA Посмотреть профиль Найти все сообщения от RUVATA
 
Регистрация: 08.02.2011
Сообщений: 41

Сообщение от Riim Посмотреть сообщение
а что это значит?
Это значит или/или:
1)Экземпляр COM-обекта в буквальном смысле захвачен процессом iexplore.exe в индивидуальном режиме (т.е. его handle принадлежит этому процессу, некую аналогию можно провести с ситуацией когда пытаетесь открыть файл который юзается какой-то софтой - если у файла есть открытый хендл, система сначала проверяет кому/какому процессу он принадлежит, потом в каком режиме он открыт, если режим индивидуальный то шлет вас "на...")...
так вот пока у IE в стеке есть хоть один хендл экземпляра COM-объекта
он всецело занят им - и рендерить сам собой ничего не будет.
Это вот как раз случай с Excel...
function Excelconnection(){
			Excel = new ActiveXObject("Excel.Application");
			Excel.Application.DisplayAlerts = false; 
			Excel.Visible = false;
			
		};

так вот пока вы не открыли док - это просто ссылка на интерфейс
а как только вы
ActiveBook = Excel.Workbooks.Open('D:\\something.xls')

это уже захваченный экземпляр COM-объекта, и исключительные права на него имеют теперь лишь он сам - процесс Excel.exe и его захватчик iexplore.exe, и просто закрыв док:
ActiveBook.Close(true)

вы не убьете захваченный экземпляр COM, вам надо убить сам процесс, т.е. закрыть апп:
Excel.Application.Quit()

вот теперь переменная Excel - снова просто ссылка на интерфейс "Excel.Application"

2)Инициализирован поток интерфейса OLE/COM... это интересный момент, это вот например:
sysShell = new ActiveXObject("Shell.Application");

здесь мы не создаем экземпляров, это потоковый интерфейс, он запущен всегда (он являются частью ОС)... и вот здесь как только мы его объявили в стеке повис поток для общения с этим интерфейсом, и пока он открыт, IE считает его как бы аналогично захваченному экземпляру(я не так силен в системном программировании чтобы описать глубже этот процесс), но в данном случае убить его можно вот так:
sysShell = null

убили ссылку на поток, поток автоматически перестал существовать.

Сообщение от Riim Посмотреть сообщение
в качестве движка для HTA-приложений используется в XP IE6 в Win7 IE7
Видимо Вы абсолютно правы... хотя я пока не бросаю попыток заставить HTML Application host в WinXP при установленном IE8 юзать именно его движок... но пока что безуспешно.

Последний раз редактировалось RUVATA, 18.08.2011 в 11:45.
Ответить с цитированием
  #5 (permalink)  
Старый 22.08.2011, 15:07
Аспирант
Отправить личное сообщение для RUVATA Посмотреть профиль Найти все сообщения от RUVATA
 
Регистрация: 08.02.2011
Сообщений: 41

Сообщение от Magneto
Для визуализации попробуйте использовать GIF-анимацию, вначале выводите гифку
то же самое...
Ответить с цитированием
  #6 (permalink)  
Старый 22.08.2011, 16:52
Аспирант
Отправить личное сообщение для RUVATA Посмотреть профиль Найти все сообщения от RUVATA
 
Регистрация: 08.02.2011
Сообщений: 41

вынести анимацию в iframe тоже не помогло...
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск