Skip to content
This repository was archived by the owner on Sep 19, 2024. It is now read-only.

Commit 5716080

Browse files
committed
Merge branch 'release/1.1.1'
2 parents 39b1dce + 7285258 commit 5716080

15 files changed

+406
-173
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
sudo: false
12
language: node_js
23
node_js:
34
- "0.10"

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
Ng-Idle  [![Build Status](https://travis-ci.org/HackedByChinese/ng-idle.png?branch=master)](https://travis-ci.org/HackedByChinese/ng-idle)
1+
Ng-Idle
22
=======
33

4+
[![Join the chat at https://gitter.im/HackedByChinese/ng-idle](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/HackedByChinese/ng-idle?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://travis-ci.org/HackedByChinese/ng-idle.png?branch=master)](https://travis-ci.org/HackedByChinese/ng-idle)
5+
46
## About
57
You may wish to detect idle users and respond, for example, to log them out so their sensitive data is protected, or taunt them, or whatever. I don't care.
68

angular-idle.js

Lines changed: 131 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*** Directives and services for responding to idle users in AngularJS
22
* @author Mike Grabski <me@mikegrabski.com>
3-
* @version v1.1.0
3+
* @version v1.1.1
44
* @link https://github.com/HackedByChinese/ng-idle.git
55
* @license MIT
66
*/
@@ -275,12 +275,28 @@ angular.module('ngIdle.idle', ['ngIdle.keepalive', 'ngIdle.localStorage'])
275275
}
276276
};
277277

278-
$document.find('body').on(options.interrupt, function() {
279-
svc.interrupt();
278+
$document.find('html').on(options.interrupt, function(event) {
279+
if (event.type === 'mousemove' && event.originalEvent && event.originalEvent.movementX === 0 && event.originalEvent.movementY === 0) {
280+
return; // Fix for Chrome desktop notifications, triggering mousemove event.
281+
}
282+
283+
/*
284+
note:
285+
webkit fires fake mousemove events when the user has done nothing, so the idle will never time out while the cursor is over the webpage
286+
Original webkit bug report which caused this issue:
287+
https://bugs.webkit.org/show_bug.cgi?id=17052
288+
Chromium bug reports for issue:
289+
https://code.google.com/p/chromium/issues/detail?id=5598
290+
https://code.google.com/p/chromium/issues/detail?id=241476
291+
https://code.google.com/p/chromium/issues/detail?id=317007
292+
*/
293+
if (event.type !== 'mousemove' || angular.isUndefined(event.movementX) || (event.movementX || event.movementY)) {
294+
svc.interrupt();
295+
}
280296
});
281297

282298
var wrap = function(event) {
283-
if (event.key === 'ngIdle.expiry' && event.newValue !== event.oldValue) {
299+
if (event.key === 'ngIdle.expiry' && event.newValue && event.newValue !== event.oldValue) {
284300
var val = angular.fromJson(event.newValue);
285301
if (val.id === id) return;
286302
svc.interrupt(true);
@@ -322,66 +338,79 @@ angular.module('ngIdle.countdown', ['ngIdle.idle'])
322338
}]);
323339

324340
angular.module('ngIdle.title', [])
325-
.factory('Title', ['$document', '$interpolate', function($document, $interpolate) {
341+
.provider('Title', function() {
342+
var options = {
343+
enabled: true
344+
};
345+
346+
var setEnabled = this.enabled = function(enabled) {
347+
options.enabled = enabled === true;
348+
};
326349

327350
function padLeft(nr, n, str){
328351
return new Array(n-String(nr).length+1).join(str||'0')+nr;
329352
}
330353

331-
var state = {
332-
original: null,
333-
idle: '{{minutes}}:{{seconds}} until your session times out!',
334-
timedout: 'Your session has expired.'
335-
};
336-
337-
return {
338-
original: function(val) {
339-
if (angular.isUndefined(val)) return state.original;
340-
341-
state.original = val;
342-
},
343-
store: function(overwrite) {
344-
if (overwrite || !state.original) state.original = this.value();
345-
},
346-
value: function(val) {
347-
if (angular.isUndefined(val)) return $document[0].title;
348-
349-
$document[0].title = val;
350-
},
351-
idleMessage: function(val) {
352-
if (angular.isUndefined(val)) return state.idle;
353-
354-
state.idle = val;
355-
},
356-
timedOutMessage: function(val) {
357-
if (angular.isUndefined(val)) return state.timedout;
358-
359-
state.timedout = val;
360-
},
361-
setAsIdle: function(countdown) {
362-
this.store();
363-
364-
var remaining = { totalSeconds: countdown };
365-
remaining.minutes = Math.floor(countdown/60);
366-
remaining.seconds = padLeft(countdown - remaining.minutes * 60, 2);
367-
368-
this.value($interpolate(this.idleMessage())(remaining));
369-
},
370-
setAsTimedOut: function() {
371-
this.store();
354+
this.$get = ['$document', '$interpolate', function($document, $interpolate) {
355+
var state = {
356+
original: null,
357+
idle: '{{minutes}}:{{seconds}} until your session times out!',
358+
timedout: 'Your session has expired.'
359+
};
372360

373-
this.value(this.timedOutMessage());
374-
},
375-
restore: function() {
376-
if (this.original()) this.value(this.original());
377-
}
378-
};
379-
}])
361+
return {
362+
setEnabled: setEnabled,
363+
isEnabled: function() {
364+
return options.enabled;
365+
},
366+
original: function(val) {
367+
if (angular.isUndefined(val)) return state.original;
368+
369+
state.original = val;
370+
},
371+
store: function(overwrite) {
372+
if (overwrite || !state.original) state.original = this.value();
373+
},
374+
value: function(val) {
375+
if (angular.isUndefined(val)) return $document[0].title;
376+
377+
$document[0].title = val;
378+
},
379+
idleMessage: function(val) {
380+
if (angular.isUndefined(val)) return state.idle;
381+
382+
state.idle = val;
383+
},
384+
timedOutMessage: function(val) {
385+
if (angular.isUndefined(val)) return state.timedout;
386+
387+
state.timedout = val;
388+
},
389+
setAsIdle: function(countdown) {
390+
this.store();
391+
392+
var remaining = { totalSeconds: countdown };
393+
remaining.minutes = Math.floor(countdown/60);
394+
remaining.seconds = padLeft(countdown - remaining.minutes * 60, 2);
395+
396+
this.value($interpolate(this.idleMessage())(remaining));
397+
},
398+
setAsTimedOut: function() {
399+
this.store();
400+
401+
this.value(this.timedOutMessage());
402+
},
403+
restore: function() {
404+
if (this.original()) this.value(this.original());
405+
}
406+
};
407+
}];
408+
})
380409
.directive('title', ['Title', function(Title) {
381410
return {
382411
restrict: 'E',
383412
link: function($scope, $element, $attr) {
384-
if ($attr.idleDisabled) return;
413+
if (!Title.isEnabled() || $attr.idleDisabled) return;
385414

386415
Title.store(true);
387416

@@ -405,9 +434,50 @@ angular.module('ngIdle.title', [])
405434
}]);
406435

407436
angular.module('ngIdle.localStorage', [])
408-
.service('IdleLocalStorage', ['$window', function($window) {
409-
var storage = $window.localStorage;
410-
437+
.service('IdleStorageAccessor', ['$window', function($window) {
438+
return {
439+
get: function() {
440+
return $window.localStorage;
441+
}
442+
}
443+
}])
444+
.service('IdleLocalStorage', ['IdleStorageAccessor', function(IdleStorageAccessor) {
445+
function AlternativeStorage() {
446+
var storageMap = {};
447+
448+
this.setItem = function (key, value) {
449+
storageMap[key] = value;
450+
};
451+
452+
this.getItem = function (key) {
453+
if(typeof storageMap[key] !== 'undefined' ) {
454+
return storageMap[key];
455+
}
456+
return null;
457+
};
458+
459+
this.removeItem = function (key) {
460+
storageMap[key] = undefined;
461+
};
462+
}
463+
464+
function getStorage() {
465+
try {
466+
var s = IdleStorageAccessor.get();
467+
s.setItem('ngIdleStorage', '');
468+
s.removeItem('ngIdleStorage');
469+
470+
return s;
471+
} catch(err) {
472+
return new AlternativeStorage();
473+
}
474+
}
475+
476+
// Safari, in Private Browsing Mode, looks like it supports localStorage but all calls to setItem
477+
// throw QuotaExceededError. We're going to detect this and just silently drop any calls to setItem
478+
// to avoid the entire page breaking, without having to do a check at each usage of Storage.
479+
var storage = getStorage();
480+
411481
return {
412482
set: function(key, value) {
413483
storage.setItem('ngIdle.'+key, angular.toJson(value));
@@ -417,8 +487,11 @@ angular.module('ngIdle.localStorage', [])
417487
},
418488
remove: function(key) {
419489
storage.removeItem('ngIdle.'+key);
490+
},
491+
_wrapped: function() {
492+
return storage;
420493
}
421494
};
422-
}]);
495+
}]);
423496

424497
})(window, window.angular);

0 commit comments

Comments
 (0)