Чи можливо виявити " неробочий " час у JavaScript?
Моїм основним випадком використання, мабуть, було б попереднє завантаження або попереднє завантаження вмісту.
Час очікування: Період бездіяльності користувача або без використання ЦП
Чи можливо виявити " неробочий " час у JavaScript?
Моїм основним випадком використання, мабуть, було б попереднє завантаження або попереднє завантаження вмісту.
Час очікування: Період бездіяльності користувача або без використання ЦП
Відповіді:
Ось простий скрипт з використанням JQuery, який обробляє події миші та натискання клавіш. Якщо час закінчується, сторінка перезавантажується.
<script type="text/javascript">
var idleTime = 0;
$(document).ready(function () {
//Increment the idle time counter every minute.
var idleInterval = setInterval(timerIncrement, 60000); // 1 minute
//Zero the idle timer on mouse movement.
$(this).mousemove(function (e) {
idleTime = 0;
});
$(this).keypress(function (e) {
idleTime = 0;
});
});
function timerIncrement() {
idleTime = idleTime + 1;
if (idleTime > 19) { // 20 minutes
window.location.reload();
}
}
</script>
setInterval, який потім оцінюється як JavaScript.
idleTime++;замість цьогоidleTime = idleTime + 1;
'mousemove keydown click'використання бітових прапорів ( Event.MOUSEMOVE | Event.KEYDOWN | Event.CLICK), оскільки вони швидше, ніж рядкові операції. Але чи справді ти хочеш це зробити?
Без використання jQuery, лише ванільний JavaScript:
var inactivityTime = function () {
var time;
window.onload = resetTimer;
// DOM Events
document.onmousemove = resetTimer;
document.onkeypress = resetTimer;
function logout() {
alert("You are now logged out.")
//location.href = 'logout.html'
}
function resetTimer() {
clearTimeout(time);
time = setTimeout(logout, 3000)
// 1000 milliseconds = 1 second
}
};
І запустіть функцію там, де вона вам потрібна (наприклад: onPageLoad).
window.onload = function() {
inactivityTime();
}
Ви можете додати більше подій DOM, якщо потрібно. Найчастіше використовуються:
document.onload = resetTimer;
document.onmousemove = resetTimer;
document.onmousedown = resetTimer; // touchscreen presses
document.ontouchstart = resetTimer;
document.onclick = resetTimer; // touchpad clicks
document.onkeypress = resetTimer;
document.addEventListener('scroll', resetTimer, true); // improved; see comments
Або зареєструйте потрібні події за допомогою масиву
window.addEventListener('load', resetTimer, true);
var events = ['mousedown', 'mousemove', 'keypress', 'scroll', 'touchstart'];
events.forEach(function(name) {
document.addEventListener(name, resetTimer, true);
});
Список подій DOM : http://www.w3schools.com/jsref/dom_obj_event.asp
Пам'ятайте про використання windowабо documentвідповідно до своїх потреб. Тут ви можете побачити відмінності між ними: Яка різниця між вікном, екраном та документом у Javascript?
Код, оновлений на @ frank-conijn та @daxchen, покращиться: window.onscrollне запуститься, якщо прокрутка знаходиться всередині прокручуваного елемента, оскільки події прокрутки не спливають. window.addEventListener('scroll', resetTimer, true), третій аргумент говорить слухачеві вловлювати подію під час фази захоплення замість фази бульбашки.
document.onload = function () { inactivityTime(); }; document.onmousedown = function () { inactivityTime(); }; document.onkeypress = function () { inactivityTime(); }; document.ontouchstart = function () { inactivityTime(); };
Покращення відповіді Еквіман:
function idleLogout() {
var t;
window.onload = resetTimer;
window.onmousemove = resetTimer;
window.onmousedown = resetTimer; // catches touchscreen presses as well
window.ontouchstart = resetTimer; // catches touchscreen swipes as well
window.onclick = resetTimer; // catches touchpad clicks as well
window.onkeypress = resetTimer;
window.addEventListener('scroll', resetTimer, true); // improved; see comments
function yourFunction() {
// your function for too long inactivity goes here
// e.g. window.location.href = 'logout.php';
}
function resetTimer() {
clearTimeout(t);
t = setTimeout(yourFunction, 10000); // time is in milliseconds
}
}
idleLogout();
.
Окрім вдосконалень щодо виявлення активності та переходу documentна режим window, цей сценарій насправді викликає функцію, а не дозволяє їй сидіти в режимі очікування.
Він не вловлює нульове використання процесора безпосередньо, але це неможливо, оскільки виконання функції викликає використання процесора. І бездіяльність користувача врешті-решт призводить до нульового використання процесора, тому опосередковано він зафіксує нульове використання процесора.
window.onscrollне буде запускатись, якщо прокрутка знаходиться всередині прокручуваного елемента, оскільки події прокрутки не спливають. Використовуючи window.addEventListener('scroll', resetTimer, true)третій аргумент, що спонукає слухача зловити подію під час captureфази замість bubbleфази (IE> 8), дивіться цю відповідь
document.onscrollтієї самої проблеми, не стріляючи, якщо прокрутка знаходиться в дитячій програмі?
addEventListenerзамість цього onscroll.
Я створив маленьку губку, яка робить це рік тому:
https://github.com/shawnmclean/Idle.js
Опис:
Крихітна бібліотека javascript для повідомлення про активність користувача у браузері (у режимі очікування, у режимі очікування, не дивлячись на веб-сторінку, на іншій вкладці тощо). це не залежить від будь-яких інших бібліотек javascript, таких як jquery.
Користувачі Visual Studio можуть отримати її від NuGet: PM> Install-Package Idle.js
Ось приблизна реалізація ідеї tvanfosson jQuery:
$(document).ready(function(){
idleTime = 0;
//Increment the idle time counter every second.
var idleInterval = setInterval(timerIncrement, 1000);
function timerIncrement()
{
idleTime++;
if (idleTime > 2)
{
doPreload();
}
}
//Zero the idle timer on mouse movement.
$(this).mousemove(function(e){
idleTime = 0;
});
function doPreload()
{
//Preload images, etc.
}
})
setIntervalструну! Просто дайте функцію як змінну!
setInterval()оцінки виразу в глобальній області, і, таким чином, він не знайде timerIncrement()функції, яка знаходиться всередині функції вже обробника. Це ще одна причина НІКОЛИ не передавати рядки setInterval(). Просто передайте фактичну посилання на функцію, і ви не матимете цієї проблеми, оскільки вони оцінені в поточній області.
Подібно до рішення Iconic вище (із власною подією jQuery) ...
// use jquery-idle-detect.js script below
$(window).on('idle:start', function(){
//start your prefetch etc here...
});
$(window).on('idle:stop', function(){
//stop your prefetch etc here...
});
//jquery-idle-detect.js
(function($,$w){
// expose configuration option
// idle is triggered when no events for 2 seconds
$.idleTimeout = 2000;
// currently in idle state
var idle = false;
// handle to idle timer for detection
var idleTimer = null;
//start idle timer and bind events on load (not dom-ready)
$w.on('load', function(){
startIdleTimer();
$w.on('focus resize mousemove keyup', startIdleTimer)
.on('blur',idleStart) //force idle when in a different tab/window
;
]);
function startIdleTimer() {
clearTimeout(idleTimer); //clear prior timer
if (idle) $w.trigger('idle:stop'); //if idle, send stop event
idle = false; //not idle
var timeout = ~~$.idleTimeout; // option to integer
if (timeout <= 100) timeout = 100; // min 100ms
if (timeout > 300000) timeout = 300000; // max 5 minutes
idleTimer = setTimeout(idleStart, timeout); //new timer
}
function idleStart() {
if (!idle) $w.trigger('idle:start');
idle = true;
}
}(window.jQuery, window.jQuery(window)))
Ви можете зробити це більш елегантно за допомогою підкреслення та jquery -
$('body').on("click mousemove keyup", _.debounce(function(){
// do preload here
}, 1200000)) // 20 minutes debounce
Моя відповідь була натхненна відповіддю vijay , але це коротше, більш загальне рішення, яке, я думав, поділюсь для когось, кому це може допомогти.
(function () {
var minutes = true; // change to false if you'd rather use seconds
var interval = minutes ? 60000 : 1000;
var IDLE_TIMEOUT = 3; // 3 minutes in this example
var idleCounter = 0;
document.onmousemove = document.onkeypress = function () {
idleCounter = 0;
};
window.setInterval(function () {
if (++idleCounter >= IDLE_TIMEOUT) {
window.location.reload(); // or whatever you want to do
}
}, interval);
}());
Наразі цей код буде виконаний негайно та перезавантажить вашу поточну сторінку через 3 хвилини без руху миші або натискання клавіш.
Для цього використовується звичайний JavaScript ванілі та вираження функції, що негайно викликається, для чистого та автономного керування непрацюючими тайм-аутами.
onclickзавдання, оскільки це, мабуть, не потрібно окрім onmousemove, але очевидно, що будь-яка з цих подій, які запускаються програмно, продовжуватиме скидання idleCounter. Я не впевнений, чому б ви імітували взаємодію користувачів замість того, щоб просто викликати функцію, але якщо це потрібно зробити чомусь, ця відповідь, очевидно, не підійде для вас, а також більшість інших відповідей я ' я дивився на це питання.
Я знаю це відносно старе питання, але у мене було те саме питання, і я знайшов досить вдале рішення.
Я використовував: jquery.idle, і мені потрібно було лише зробити:
$(document).idle({
onIdle: function(){
alert('You did nothing for 5 seconds');
},
idle: 5000
})
Див. Демонстрацію JsFiddle .
(Тільки для інформації: перегляньте це для відстеження подій в кінцевому підсумку )
keepTrackingпараметр на false. Якщо ви хочете скинути, ви можете спробувати повторно реалізувати. Ось модифікований приклад, який запускається лише один раз: jsfiddle.net/f238hchm/12
Усі попередні відповіді мають завжди активний обробник миші. Якщо обробник jQuery, додаткова обробка, яку виконує jQuery, може скласти. Особливо, якщо користувач використовує ігрову мишу, може статися аж 500 подій в секунду.
Це рішення дозволяє уникнути обробки кожної події в русі миші. Це призводить до невеликої помилки в часі, але яку ви можете налаштувати під свої потреби.
function setIdleTimeout(millis, onIdle, onUnidle) {
var timeout = 0;
startTimer();
function startTimer() {
timeout = setTimeout(onExpires, millis);
document.addEventListener("mousemove", onActivity);
document.addEventListener("keydown", onActivity);
}
function onExpires() {
timeout = 0;
onIdle();
}
function onActivity() {
if (timeout) clearTimeout(timeout);
else onUnidle();
//since the mouse is moving, we turn off our event hooks for 1 second
document.removeEventListener("mousemove", onActivity);
document.removeEventListener("keydown", onActivity);
setTimeout(startTimer, 1000);
}
}
$(startTimer)еквівалент $(document).ready(startTimer)гарантує, що DOM буде готовий до того, як підключити події миші та натискання клавіш.
Можливо, ви могли б зламати щось разом, виявивши рух миші на тілі форми та оновивши глобальну змінну з останнім часом руху. Тоді вам знадобиться запустити таймер інтервалу, який періодично перевіряє останній час руху і робить щось, якщо це було достатньо довго з моменту виявлення останнього руху миші.
Я написав невеликий клас ES6 для виявлення активності та інших випадків пожежі в режимі очікування. Він охоплює клавіатуру, мишу та сенсорний режим , може бути активований та деактивований та має дуже худий API:
const timer = new IdleTimer(() => alert('idle for 1 minute'), 1000 * 60 * 1);
timer.activate();
Це не залежить від jQuery, хоча вам може знадобитися запустити його через Babel для підтримки старих браузерів.
https://gist.github.com/4547ef5718fd2d31e5cdcafef0208096
Я можу випустити його як пакет npm, як тільки отримаю відгук.
Якщо ви орієнтовані на підтримуваний веб-переглядач (Chrome або Firefox станом на грудень 2018 року), ви можете експериментувати з requestIdleCallback і включити прошивку requestIdleCallback для непідтримуваних веб-переглядачів.
Спробуйте цей код, він прекрасно працює.
var IDLE_TIMEOUT = 10; //seconds
var _idleSecondsCounter = 0;
document.onclick = function () {
_idleSecondsCounter = 0;
};
document.onmousemove = function () {
_idleSecondsCounter = 0;
};
document.onkeypress = function () {
_idleSecondsCounter = 0;
};
window.setInterval(CheckIdleTime, 1000);
function CheckIdleTime() {
_idleSecondsCounter++;
var oPanel = document.getElementById("SecondsUntilExpire");
if (oPanel)
oPanel.innerHTML = (IDLE_TIMEOUT - _idleSecondsCounter) + "";
if (_idleSecondsCounter >= IDLE_TIMEOUT) {
alert("Time expired!");
document.location.href = "SessionExpired.aspx";
}
}
<script type="text/javascript">
var idleTime = 0;
$(document).ready(function () {
//Increment the idle time counter every minute.
idleInterval = setInterval(timerIncrement, 60000); // 1 minute
//Zero the idle timer on mouse movement.
$('body').mousemove(function (e) {
//alert("mouse moved" + idleTime);
idleTime = 0;
});
$('body').keypress(function (e) {
//alert("keypressed" + idleTime);
idleTime = 0;
});
$('body').click(function() {
//alert("mouse moved" + idleTime);
idleTime = 0;
});
});
function timerIncrement() {
idleTime = idleTime + 1;
if (idleTime > 10) { // 10 minutes
window.location.assign("http://www.google.com");
}
}
</script>
Я думаю, що цей код jquery є ідеальним, хоча він скопійований і змінений вище з відповідей !! не забув включити бібліотеку jquery у свій файл!
Проблема з усіма цими рішеннями, хоча і правильна, але непрактична, якщо враховувати цінний набір сеансу очікування сеансу, використовуючи PHP, .NET або у файлі Application.cfc для розробників Coldfusion. Час, встановлений вищевказаним рішенням, повинен синхронізуватися з час очікування сеансу на стороні сервера. Якщо вони не синхронізуються, ви можете зіткнутися з проблемами, які просто засмутять і заплутають ваших користувачів. Наприклад, час очікування сеансу на стороні сервера може бути встановлений на 60 хвилин, але користувач може вважати, що він / вона в безпеці, оскільки захоплення в режимі очікування JavaScript збільшило загальну кількість часу, який користувач може провести на одній сторінці. Користувач, можливо, витратив час на заповнення довгої форми, а потім переходить до його надсилання. Час очікування сеансу може розпочатися до того, як буде оброблено подання форми. Я схильний просто давати своїм користувачам 180 хвилин, а потім скористайтеся JavaScript, щоб автоматично вийти з користувача. По суті, використовуючи деякий код вище, щоб створити простий таймер, але без захоплення частини події миші. Таким чином час мого клієнта та серверний час ідеально синхронізуються. Немає плутанини, якщо ви показуєте користувачеві час у своєму інтерфейсі, оскільки він скорочується. Кожен раз, коли доступ до нової сторінки в CMS, сеанс на сервері та таймер JavaScript скидаються. Простий та елегантний. Якщо користувач залишається на одній сторінці більше 180 хвилин, я вважаю, що зі сторінкою щось не так. як зменшує. Кожен раз, коли доступ до нової сторінки в CMS, сеанс на сервері та таймер JavaScript скидаються. Простий та елегантний. Якщо користувач залишається на одній сторінці більше 180 хвилин, я вважаю, що зі сторінкою щось не так. як зменшує. Кожен раз, коли доступ до нової сторінки в CMS, сеанс на сервері та таймер JavaScript скидаються. Простий та елегантний. Якщо користувач залишається на одній сторінці більше 180 хвилин, я вважаю, що зі сторінкою щось не так.
Чистий JavaScript з правильно встановленим часом скидання та прив’язками через addEventListener
(function() {
var t,
timeout = 5000;
function resetTimer() {
console.log("reset: " + new Date().toLocaleString());
if (t) {
window.clearTimeout(t);
}
t = window.setTimeout(logout, timeout);
}
function logout() {
console.log("done: " + new Date().toLocaleString());
}
resetTimer();
//And bind the events to call `resetTimer()`
["click", "mousemove", "keypress"].forEach(function(name) {
console.log(name);
document.addEventListener(name, resetTimer);
});
}());
(Частково натхненний хорошою логікою Еквімана раніше в цій темі.)
sessionExpiration.js - це легкий, але ефективний і налаштований. Після впровадження використовуйте лише один ряд:
sessionExpiration(idleMinutes, warningMinutes, logoutUrl);
Це приклад того, як це виглядає в дії, якщо ви не змінюєте CSS.
Я написав простий плагін jQuery, який зробить те, що ви шукаєте.
https://github.com/afklondon/jquery.inactivity
$(document).inactivity( {
interval: 1000, // the timeout until the inactivity event fire [default: 3000]
mouse: true, // listen for mouse inactivity [default: true]
keyboard: false, // listen for keyboard inactivity [default: true]
touch: false, // listen for touch inactivity [default: true]
customEvents: "customEventName", // listen for custom events [default: ""]
triggerAll: true, // if set to false only the first "activity" event will be fired [default: false]
});
Сценарій буде прослуховувати миші, клавіатури, сенсорні та інші користувацькі події бездіяльності (простою) та глобальних подій "активності" та "бездіяльності".
Сподіваюся, це допомагає :)
Всього кілька думок, проспект-два, щоб дослідити.
Чи можна запускати функцію кожні 10 секунд і перевіряти змінну "лічильник"? Якщо це можливо, ви можете мати курсор миші для сторінки, чи не так? Якщо так, використовуйте подію миші, щоб скинути змінну "лічильник". Якщо ваша функція викликана, а лічильник вище діапазону, який ви заздалегідь визначите, то виконайте свої дії.
Знову лише кілька думок ... Сподіваюся, це допомагає.
Я перевірив цей робочий файл коду:
var timeout = null;
var timee = '4000'; // default time for session time out.
$(document).bind('click keyup mousemove', function(event) {
if (timeout !== null) {
clearTimeout(timeout);
}
timeout = setTimeout(function() {
timeout = null;
console.log('Document Idle since '+timee+' ms');
alert("idle window");
}, timee);
});
Ось найкраще рішення, яке я знайшов: http://css-tricks.com/snippets/jquery/fire-event-when-user-is-idle/
Ось JS:
idleTimer = null;
idleState = false;
idleWait = 2000;
(function ($) {
$(document).ready(function () {
$('*').bind('mousemove keydown scroll', function () {
clearTimeout(idleTimer);
if (idleState == true) {
// Reactivated event
$("body").append("<p>Welcome Back.</p>");
}
idleState = false;
idleTimer = setTimeout(function () {
// Idle Event
$("body").append("<p>You've been idle for " + idleWait/1000 + " seconds.</p>");
idleState = true; }, idleWait);
});
$("body").trigger("mousemove");
});
}) (jQuery)
Можна скористатися наведеним нижче рішенням
var idleTime;
$(document).ready(function () {
reloadPage();
$('html').bind('mousemove click mouseup mousedown keydown keypress keyup submit change mouseenter scroll resize dblclick', function () {
clearTimeout(idleTime);
reloadPage();
});
});
function reloadPage() {
clearTimeout(idleTime);
idleTime = setTimeout(function () {
location.reload();
}, 3000);
}
Я використовую такий підхід, оскільки вам не потрібно постійно скидати час, коли відбувається подія, натомість ми просто записуємо час, це створює початкову точку простою.
function idle(WAIT_FOR_MINS, cb_isIdle) {
var self = this,
idle,
ms = (WAIT_FOR_MINS || 1) * 60000,
lastDigest = new Date(),
watch;
//document.onmousemove = digest;
document.onkeypress = digest;
document.onclick = digest;
function digest() {
lastDigest = new Date();
}
// 1000 milisec = 1 sec
watch = setInterval(function(){
if (new Date() - lastDigest > ms && cb_isIdel) {
clearInterval(watch);
cb_isIdle();
}
}, 1000*60);
},
Ви, ймовірно, можете виявити бездіяльність на своїй веб-сторінці за допомогою перелічених хитрощів миші, але це не скаже вам, що користувач не перебуває на іншій сторінці в іншому вікні чи вкладці, або що користувач перебуває в Word або Photoshop, або WOW і наразі просто не переглядає вашу сторінку. Як правило, я б просто зробив попередній вибір і покладався на багатозадачність клієнта. Якщо ви насправді потрібна ця функціональність, ви робите щось із керуванням ActiveX у Windows, але це в кращому випадку некрасиво.
Ось послуга AngularJS для виконання в Angular.
/* Tracks now long a user has been idle. secondsIdle can be polled
at any time to know how long user has been idle. */
fuelServices.factory('idleChecker',['$interval', function($interval){
var self = {
secondsIdle: 0,
init: function(){
$(document).mousemove(function (e) {
self.secondsIdle = 0;
});
$(document).keypress(function (e) {
self.secondsIdle = 0;
});
$interval(function(){
self.secondsIdle += 1;
}, 1000)
}
}
return self;
}]);
Майте на увазі, що ця перевірка буде запущена для всіх маршрутів, тому її слід ініціалізувати під час .run()завантаження кутового додатка. Потім ви можете використовувати idleChecker.secondsIdleвсередині кожного маршруту.
myApp.run(['idleChecker',function(idleChecker){
idleChecker.init();
}]);
Debounce насправді чудова ідея! Ось версія для безкоштовних проектів jQuery:
const derivedLogout = createDerivedLogout(30);
derivedLogout(); // it could happen that user too idle)
window.addEventListener('click', derivedLogout, false);
window.addEventListener('mousemove', derivedLogout, false);
window.addEventListener('keyup', derivedLogout, false);
function createDerivedLogout (sessionTimeoutInMinutes) {
return _.debounce( () => {
window.location = this.logoutUrl;
}, sessionTimeoutInMinutes * 60 * 1000 )
}
Настільки просто, наскільки це можливо, виявляйте, коли миша рухається лише:
var idle = false;
document.querySelector('body').addEventListener('mousemove', function(e) {
if(idle!=false)idle = false;
});
var idleI = setInterval(function()
{
if(idle == 'inactive')
{
return;
}
if(idle == true)
{
idleFunction();
idle = 'inactive';
return;
}
idle = true;
}, 30000);// half the expected time, idle will trigger after 60s in this case.
function idleFuntion()
{
console.log('user is idle');
}
Добре, ви можете приєднати подію натискання або переміщення миші до тіла документа, яке скидає таймер. Отримайте функцію, яку ви викликаєте через тимчасові інтервали, яка перевіряє, чи таймер перевищує визначений час (наприклад, 1000 міліс), і розпочніть попереднє завантаження.
У Javascript немає способу розповісти про використання процесора. Це призведе до порушення функціонування javascript у пісочниці всередині.
Крім цього, підключення подій onmouseover та onkeydown сторінки, ймовірно, спрацює.
Ви також можете встановити використання setTimeout у події завантаження для планування функції, яку слід викликати після затримки.
// Call aFunction after 1 second
window.setTimeout(aFunction, 1000);