Author |
Message |
K.Wiolowan
Участник форума
Joined: 22 Feb 2006
Posts: 53
Карма: 11 поощрить/наказать
|
Posted: Wed May 27, 2009 4:08 pm (написано за 4 минуты 24 секунды)
Post subject: onIdle
|
|
А действительно, можно ли сделать такой маленький фреймворк, чтобы на момент бездействия пользователя делать потихоньку, по частям какую-то свою ресурсоемкую работу - которая в случае выполнения ее при начальной загрузке, надолго бы подвешивала компьютера... Как-нибудь так (это, конечно, сырая глючная и не универсальная концепция): allanguages.info/onmousemoveend.html Code (JavaScript): | скопировать код в буфер обмена | var idleManager ={ id:null, idleWrapper: function(func,param,lag,repeat) { lag = lag || 500; repeat = repeat || 100; return function() { if (idleManager.id) { clearTimeout(idleManager.id); document.getElementById('output').innerHTML= 'Busy with a user..'; } idleManager.id = setTimeout(function() { func(param) idleManager.id=setTimeout(arguments.callee, repeat) }, lag); } }, start: function(func, param, lag, repeat){ window.onload= idleManager.idleWrapper(func, param, lag, repeat) document.onkeyup = idleManager.idleWrapper(func, param, lag, repeat) document.onmousemove = idleManager.idleWrapper(func, param, lag, repeat) } }
idleManager.start(function(param){ for(var s=0,i=0; i<100000; i++) s+=i document.getElementById('output').innerHTML= 'Idling '+(param.count++)+'th time; counted sum='+s+'<br /> Move your mouse or start typing..'; }, {count:0}, 1000, 200 ) | Навеяно этим: www.matts411.com/post/delaying_javascript_event_execution/
|
|
Back to top |
|
 |
K.Wiolowan
Участник форума
Joined: 22 Feb 2006
Posts: 53
Карма: 11 поощрить/наказать
|
Posted: Wed May 27, 2009 4:18 pm (спустя 9 минут; написано за 1 минуту 34 секунды)
Post subject:
|
|
В качестве частной подзадачи хотелось бы отслеживать "onMouseMoveEnd" без 35-90%-ной загрузки процессора, как у Matt'a. Включать и отключать onmousemove по setTimeout, что ли...
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Thu May 28, 2009 8:12 pm (спустя 1 день 3 часа 54 минуты; написано за 3 минуты 5 секунд)
Post subject:
|
|
K.Wiolowan, очень интересная идея. Я предлагаю и сразу выкладываю чуть поправленый код. Второй аргумент метода start, лучше сделать массивом, а в последующем, функцию-коллбэк (из первого аргумента) вызывать через apply. Code (JavaScript): | скопировать код в буфер обмена | var idleManager = { id: null,
idleWrapper: function(func, param, lag, repeat) { lag = lag || 500; repeat = repeat || 100; return function() { if (idleManager.id) { clearTimeout(idleManager.id); document.getElementById('output').innerHTML = 'Busy with a user..'; }
idleManager.id = setTimeout(function() { func.apply(window, param); idleManager.id = setTimeout(arguments.callee, repeat); }, lag); } },
start: function(func, param, lag, repeat) { window.onload = idleManager.idleWrapper(func, param, lag, repeat); document.onkeyup = idleManager.idleWrapper(func, param, lag, repeat); document.onmousemove = idleManager.idleWrapper(func, param, lag, repeat); } }
idleManager.start(function(param) { for (var s = 0, i = 0; i < 100000; i++) s+=i; document.getElementById('output').innerHTML = 'Idling ' + (param.count++) + 'th time; counted sum=' + s + '<br /> Move your mouse or start typing..'; }, [{count:0}], 1000, 200); |
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Fri May 29, 2009 5:39 am (спустя 9 часов 26 минут; написано за 1 минуту 11 секунд)
Post subject:
|
|
K.Wiolowan, также, устанавливать таймаут при каждом вызове функции коллбэка для таймаута -- не особо оптимально. Поэтому заменяю setTimeout => setInterval. Code (JavaScript): | скопировать код в буфер обмена | var idleManager = { timeout_id: null, interval_id: null,
idleWrapper: function(func,param,lag,repeat) { lag = lag || 500; repeat = repeat || 100; return function() { if (idleManager.timeout_id) { clearTimeout(idleManager.timeout_id); clearInterval(idleManager.interval_id); document.getElementById('output').innerHTML= 'Busy with a user..'; }
idleManager.timeout_id = setTimeout(function() { func.apply(window, param);
idleManager.interval_id = setInterval(function() { func.apply(window, param); }, repeat); }, lag); } },
start: function(func, param, lag, repeat) { window.onload= idleManager.idleWrapper(func, param, lag, repeat); document.onkeyup = idleManager.idleWrapper(func, param, lag, repeat); document.onmousemove = idleManager.idleWrapper(func, param, lag, repeat); } }
idleManager.start(function(param) { for(var s=0,i=0; i<100000; i++) s+=i document.getElementById('output').innerHTML= 'Idling '+(param.count++)+'th time; counted sum='+s+'<br /> Move your mouse or start typing..'; }, [{count:0}], 1000, 200); |
|
|
Back to top |
|
 |
K.Wiolowan
Участник форума
Joined: 22 Feb 2006
Posts: 53
Карма: 11 поощрить/наказать
|
Posted: Fri May 29, 2009 7:02 am (спустя 1 час 23 минуты; написано за 6 минут 23 секунды)
Post subject:
|
|
Александр Михалицын wrote: |
K.Wiolowan, также, устанавливать таймаут при каждом вызове функции коллбэка для таймаута -- не особо оптимально. Поэтому заменяю setTimeout => setInterval. | --Спасибо, Александр, Вашу версию выложил здесь: allanguages.info/onmousemoveend2.html (цикл idle-фунции 100 000 суммаций) allanguages.info/onmousemoveend3.html (цикл idle-фунции 5 000 000 суммаций) Все же, setTimeout, ИМХО, надежнее и точнее setInterval: setTimeout(func, 100) гарантирует минимальную паузу в 100 мсек, в то время как в некоторых условиях setInterval(func, 100) может выполняться вообще практически без задержек, если сама func выполняется, скажем, за 99 мсек. Одним словом, второй параметр в setInterval и setTimeout имеет разные смыслы. ejohn.org/blog/how-javascript-timers-work/ : Quote: |
Let's take a look at an example to better illustrate the differences between setTimeout and setInterval. Code (JavaScript): | скопировать код в буфер обмена | setTimeout(function(){ /* Some long block of code... */ setTimeout(arguments.callee, 10); }, 10); setInterval(function(){ /* Some long block of code... */ }, 10); | These two pieces of code may appear to be functionally equivalent, at first glance, but they are not. Notably the setTimeout code will always have at least a 10ms delay after the previous callback execution (it may end up being more, but never less) whereas the setInterval will attempt to execute a callback every 10ms regardless of when the last callback was executed. |
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Fri May 29, 2009 7:59 am (спустя 56 минут; написано за 4 минуты 45 секунд)
Post subject:
|
|
K.Wiolowan, хм... Значит оставляем Timeout? Ну хорошо... ;) Предлагаю сделать второй коллбэк, который будет вызываться когда пользователь начал свою активность... Code (JavaScript): | скопировать код в буфер обмена | var idleManager = { id: null,
idleWrapper: function(func, param, func_end, param_end, lag, repeat) { lag = lag || 500; repeat = repeat || 100; return function() { if (idleManager.id) { clearTimeout(idleManager.id); func_end.apply(window, param_end); }
idleManager.id = setTimeout(function() { func.apply(window, param); idleManager.id = setTimeout(arguments.callee, repeat); }, lag); } },
start: function(func, param, func_end, param_end, lag, repeat) { window.onload = idleManager.idleWrapper(func, func_end, param_end, param, lag, repeat); document.onkeyup = idleManager.idleWrapper(func, param, func_end, param_end, lag, repeat); document.onmousemove = idleManager.idleWrapper(func, param, func_end, param_end, lag, repeat); } }
idleManager.start(function(param) { for (var s = 0, i = 0; i < 100000; i++) s+=i; document.getElementById('output').innerHTML = 'Idling ' + (param.count++) + 'th time; counted sum=' + s + '<br /> Move your mouse or start typing..'; }, [{count:0}], function() { document.getElementById('output').innerHTML = 'Busy with a user..'; }, [], 1000, 200); | Скоро все это дело разрастется и интерфейс станет сложным, видимо нужно написать все по-другому... (Я наверно к вечеру выложу свой вариант интерфейса библиотеки....) Предлагаю также возможность вызова функции func не через промежуток времени, а только один раз. Тоесть пользователь дернул мышь, потом остановил, функция вызвалась и все, потом опять дернул, остановил, опять вызвалась... ИМХО, может быть полезно...
|
|
Back to top |
|
 |
K.Wiolowan
Участник форума
Joined: 22 Feb 2006
Posts: 53
Карма: 11 поощрить/наказать
|
Posted: Fri May 29, 2009 8:59 am (спустя 59 минут; написано за 14 минут 36 секунд)
Post subject:
|
|
Александр Михалицын wrote: |
хм... Значит оставляем Timeout? Ну хорошо... ;) | --Да, и в случае, если повторяемая функция выполняется дольше, чем интервал - тоже могут, насколько я понял, быть проблемы. Александр Михалицын wrote: |
Предлагаю сделать второй коллбэк, который будет вызываться когда пользователь начал свою активность... | --Да, конечно, причем второй коллбэк может быть и не определен... Александр Михалицын wrote: |
| --А вот интересно, можно ли сделать так, чтобы param, param_end становились перекрытиями, closures, чтобы func, func_end не передавать их в виде параметров? Хотя, если передача через лок.параметры быстрее, то нечего и дергаться... Александр Михалицын wrote: |
Скоро все это дело разрастется и интерфейс станет сложным, видимо нужно написать все по-другому... (Я наверно к вечеру выложу свой вариант интерфейса библиотеки....) | --Было бы интересно взглянуть. Если Вам удасться проконтролировать onMouseMove в виде установки и стирания таймаутов с document.onmousemove=..., т.е., не напрягая процессор - было бы вообще здорово. Кстати, не знаю почему, но примеры из www.matts411.com/post/delaying_javascript_event_execution/ не работают внутри Firefox extension... Александр Михалицын wrote: |
Предлагаю также возможность вызова функции func не через промежуток времени, а только один раз. Тоесть пользователь дернул мышь, потом остановил, функция вызвалась и все, потом опять дернул, остановил, опять вызвалась... ИМХО, может быть полезно... | --Может быть, func просто должна возвращать true или false, в зависимости от того, нужен ли повторный запуск или нет? Это решает вопрос и однократного вызова, и многократного, когда func доделывает фоновую работу и ей больше нечего делать... Code (JavaScript): | скопировать код в буфер обмена | idleManager.id = setTimeout(function() { if(func.apply(window, param)) idleManager.id = setTimeout(arguments.callee, repeat); }, lag); |
|
|
Back to top |
|
 |
K.Wiolowan
Участник форума
Joined: 22 Feb 2006
Posts: 53
Карма: 11 поощрить/наказать
|
Posted: Fri May 29, 2009 9:13 am (спустя 14 минут; написано за 2 минуты 30 секунд)
Post subject:
|
|
P.S. нужно еще подумать насчет списка событий, по которым судить о "простое" (window.onload, document.onkeyup - лучше onkeydown?, document.onmousemove, onmousedown? скроллинг?) -и о совместимости с другими скриптами и библиотеками в вопросах обработки событий...
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Fri May 29, 2009 10:10 am (спустя 57 минут; написано за 1 минуту 24 секунды)
Post subject:
|
|
K.Wiolowan, Quote: |
--А вот интересно, можно ли сделать так, чтобы param, param_end становились перекрытиями, closures, чтобы func, func_end не передавать их в виде параметров? Хотя, если передача через лок.параметры быстрее, то нечего и дергаться... | Я как раз думаю об этом... Quote: |
--Может быть, func просто должна возвращать true или false, в зависимости от того, нужен ли повторный запуск или нет? | Хорошо. Давайте так... ;) Quote: |
-и о совместимости с другими скриптами и библиотеками в вопросах обработки событий... | Угу. Потом выложу пару функций для установки событий... (Своих)
|
|
Back to top |
|
 |
K.Wiolowan
Участник форума
Joined: 22 Feb 2006
Posts: 53
Карма: 11 поощрить/наказать
|
Posted: Fri May 29, 2009 11:52 am (спустя 1 час 42 минуты; написано за 1 минуту 15 секунд)
Post subject:
|
|
allanguages.info/onidle.html Code (JavaScript): | скопировать код в буфер обмена | idleManager = new function(){ var id=null var func_idle= null var func_busy= null var func_stop= null var lag=500 var repeat=100 var param={} this.idleWrapper= function(){ return function(){ if (id){ clearTimeout(id); if(func_busy) func_busy.apply(window, [param]); } id = setTimeout(function(){ if(func_idle.apply(window, [param])){ id = setTimeout(arguments.callee, repeat) }else{ stopIdle() if(func_stop) func_stop.apply(window, [param]); } }, lag); } } this.start= function(_func_idle, _param, _lag, _repeat, _func_busy, _func_stop ) { func_idle= _func_idle param= _param || {} func_busy= _func_busy || null func_stop= _func_stop || null lag= _lag || 500 repeat= _repeat || 100 window.onload = this.idleWrapper() document.onkeydown = this.idleWrapper() document.onmousemove = this.idleWrapper() document.onmousedown = this.idleWrapper() this.idleWrapper()() } var stopIdle= function(){ clearTimeout(id) document.onkeydown = document.onmousemove = document.onmousedown = null } this.stop = stopIdle }
function idleProcess(param){ for (var i = 0; i < 100000; i++) param.s+=i*0.000127; document.getElementById('output').innerHTML = 'Idling ' + (param.count++) + 'th time; counted sum=' + Math.floor(param.s) + '<br />Waiting for the sum to be > 50000000<br /> Move your mouse or start typing..'+ '<br />Doubleclick to stop idle process'; return param.s < 50000000 ? true : false; } idleManager.start( idleProcess, {count:0, s:0}, 1000, 200, function(){ document.getElementById('output').innerHTML = 'Busy with a user..'; }, function(){ document.getElementById('output').innerHTML = 'I\'m thru....'; } ); document.ondblclick=function(){ idleManager.stop() document.getElementById('output').innerHTML = 'Idle process stopped<br />'+ 'Doubleclick to start again' document.ondblclick=function(){ idleManager.start(idleProcess, {count:0, s:0}) } } | Обратите внимание на this.idleWrapper()() :)
|
|
Back to top |
|
 |
K.Wiolowan
Участник форума
Joined: 22 Feb 2006
Posts: 53
Карма: 11 поощрить/наказать
|
Posted: Fri May 29, 2009 12:27 pm (спустя 34 минуты; написано за 2 минуты 55 секунд)
Post subject:
|
|
А вот, к примеру, "Central Timer Control to manage multiple animations" от John Resig Code (JavaScript): | скопировать код в буфер обмена | var timers = { timerID: 0, timers: [], start: function(){ if ( this.timerID ) return; (function(){ for ( var i = 0; i < timers.timers.length; i++ ) if ( timers.timers[i]() === false ) { timers.timers.splice(i, 1); i--; } timers.timerID = setTimeout( arguments.callee, 0 ); })(); }, stop: function(){ clearTimeout( this.timerID ); this.timerID = 0; }, add: function(fn){ this.timers.push( fn ); this.start(); } };
var box = document.getElementById("box"), left = 0, top = 20; timers.add(function(){ box.style.left = left + "px"; if ( ++left > 50 ) return false; }); timers.add(function(){ box.style.top = top + "px"; top += 2; if ( top > 120 ) return false; }); | We've created a central control structure in Listing 5-4 that we can add new timer callback functions to and stop/start the execution of them. Additionally, the callback functions have the ability to remove themselves at any time by simply returning 'false' (which is much easier to do than the typical clearTimeout pattern). Let's step through the code to see how it works. To start, all of the callback functions are stored in a central array (timers.timers) alongside the ID of the current timer (timers.timerID). The real meat comes in with in the start() method. Here we need to verify that there isn't already a timer running, and if that's the case, start our central timer. This timer consists of a loop which moves through all of our callback functions, executing them in order. It also checks to see what the return value of the callback is - if it's false then the function is removed from being executed. This proves to be a much simpler manner of managing timers than One thing that's important to note: Organizing timers in this manner ensures that the callback functions will always execute in the order in which they are added. That is not always guaranteed with normal timers (the browser could choose to execute one before another). This manner of timer organization is critical for large applications or really any form of JavaScript animations.
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Fri May 29, 2009 12:52 pm (спустя 24 минуты; написано за 17 секунд)
Post subject:
|
|
K.Wiolowan, да. Примерно так себе и представлял интерфейс. Вот, правда, мой вариант. Code (JavaScript): | скопировать код в буфер обмена | /** * @description * Библиотека позволяет отлавливать момент, когда пользователь * бездействует и в этот момент запускать функцию-коллбэк, * устанавливаемую в методе init() * * @author K.Wiolowan (http://forum.dklab.ru/profile.php?mode=viewprofile&u=8644) * * Additional authors: * @author Aleksandr Michalicyn <admin@systemnik.net.ru> (http://systemnik.net.ru) (небольшие исправления) * * @version 1.1 * * @sample * * var on_not_busy = function(param1, param2) * { * document.getElementById('output').innerHTML = 'Ресурсы свободны! Я получила вследующие параметры: ' + param1 + ':' + param2; * } * * var on_busy = function(param1, param2) * { * document.getElementById('output').innerHTML = 'Ресурсы заняты! Я получила вследующие параметры: ' + param1 + ':' + param2; * } * * idleManager.start(on_not_busy, ['first', 'second'], on_busy, ['first', 'second'], 1000, 200); * */
var idleManager = new function() { var self = this;
var lag, repeat, param, func, timeout_id, func_busy, param_busy; //private properties
/** * This method set event in object. * @access private */ var set_event = function(event_type, event_interpriter, object) { if ((event_type == 'load' || event_type == 'keydown') && object == window) { object = object.document.documentElement; }
if (object.addEventListener) { object.addEventListener(event_type, event_interpriter, false); } else { object.attachEvent('on' + event_type, event_interpriter); } }
/** * This method unset event in object. * @access private */ var unset_event = function(event_type, event_interpriter, object) { if ((event_type == 'load' || event_type == 'keydown') && object == window) { object = object.document.documentElement; }
if (object.removeEventListener) { object.removeEventListener(event_type, event_interpriter, false); } else { object.detachEvent('on' + event_type, event_interpriter); } }
var idleWrapper = function() { if (timeout_id) { clearTimeout(timeout_id); func_busy.apply(window, param_busy); }
timeout_id = setTimeout(function() { if (func.apply(window, param) !== false) { idleManager.id = setTimeout(arguments.callee, repeat); } else { self.stop(); } }, lag); }
self.stop = function() { clearTimeout(timeout_id);
unset_event('load', idleWrapper, window); unset_event('keydown', idleWrapper, document); unset_event('mousemove', idleWrapper, document); unset_event('mousedown', idleWrapper, document); }
self.start = function(_func, _param, _func_busy, _param_busy, _lag, _repeat) { lag = _lag || 500; repeat = _repeat || 100; param = _param || []; func = _func || function() {}; func_busy = _func_busy || function() {}; param_busy = _param_busy || [];
set_event('load', idleWrapper, window); set_event('keydown', idleWrapper, document); set_event('mousemove', idleWrapper, document); set_event('mousedown', idleWrapper, document);
idleWrapper(); } }
//Инициализация var on_not_busy = function(param1, param2) { document.getElementById('output').innerHTML = 'Ресурсы свободны! Я получила вследующие параметры: ' + param1 + ':' + param2; }
var on_busy = function(param1, param2) { document.getElementById('output').innerHTML = 'Ресурсы заняты! Я получила вследующие параметры: ' + param1 + ':' + param2; }
idleManager.start(on_not_busy, ['йа параметр =)', 'йа второй параметр =))'], on_busy, ['йа параметр =)', 'йа второй параметр =))'], 1000, 200); |
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Fri May 29, 2009 12:59 pm (спустя 7 минут; написано за 2 минуты 2 секунды)
Post subject:
|
|
В коллбеке func_stop из вашего кода, я смысла не увидел. Поскольку если функция-коллбек func_idle, должна будет возвратить false, в её алгоритме необходимо предусмотреть все действия из коллбэка func_stop, иначе, мы получается "делим" функцию func_idle, хотя особого смысла в этом нет...
|
|
Back to top |
|
 |
Guest
Карма: 388 поощрить/наказать
|
Posted: Fri May 29, 2009 11:25 pm (спустя 10 часов 26 минут; написано за 3 минуты 31 секунду)
Post subject:
|
|
Code (JavaScript): | скопировать код в буфер обмена | function testVarsByContext(){ alert(param1+param2) } function testVarsByParams(param1, param2){ alert(param1+param2) }
testVarsByContext.apply({param1:'1', param2:2}) // alerts '12' testVarsByParams.apply(window, ['1', 2]) // alerts '12' |
|
|
Back to top |
|
 |
K.Wiolowan
Участник форума
Joined: 22 Feb 2006
Posts: 53
Карма: 11 поощрить/наказать
|
Posted: Fri May 29, 2009 11:30 pm (спустя 4 минуты; написано за 2 минуты 8 секунд)
Post subject:
|
|
Т.е., Code (JavaScript): | скопировать код в буфер обмена | ... func_busy.apply(/*window,*/ param_busy) ... var on_busy = function(/*param1, param2*/) { document.getElementById('output').innerHTML = ' ! : ' + param1 + ':' + param2; }
idleManager.start(on_not_busy, {param1:' =)', param2: ' =))'}, on_busy, {param1: ' =)', param2: ' =))'}, 1000, 200); |
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Sat May 30, 2009 10:18 am (спустя 10 часов 48 минут; написано за 57 секунд)
Post subject:
|
|
K.Wiolowan, нет-нет! Ненадо запускать функцию в контексте какого-то объекта... К чему этот изврат? Пусть остается как есть.. func.apply(контекст, массив аргументов);
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Sat May 30, 2009 10:21 am (спустя 2 минуты; написано за 56 секунд)
Post subject:
|
|
, вы ошибаетесь, первый пример не сработает. Если функция вызывается в контексте определенного объекта и нужно получить его свойство, употребление указателя на текущий контекст (this) обязательно.
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Thu Aug 20, 2009 10:36 am (спустя 2 месяца 21 день 15 минут; написано за 1 секунду)
Post subject:
|
|
forum.dklab.ru/viewtopic.php?t=34972
|
|
Back to top |
|
 |
|