├── .gitignore
├── .jshintrc
├── .npmignore
├── .travis.yml
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Gruntfile.js
├── LICENSE-MIT
├── README.md
├── bower.json
├── demos
├── autologout.html
├── autologoutsync.html
├── defaultbinding.html
├── index.html
├── respond.proxy.gif
└── respond.proxy.js
├── dist
├── idle-timer.0.9.3.js
├── idle-timer.0.9.3.min.js
├── idle-timer.1.0.0.js
├── idle-timer.1.0.0.min.js
├── idle-timer.1.0.1.js
├── idle-timer.1.0.1.min.js
├── idle-timer.1.1.0.js
├── idle-timer.1.1.0.min.js
├── idle-timer.1.1.1.js
├── idle-timer.1.1.1.min.js
├── idle-timer.js
└── idle-timer.min.js
├── idle-timer.jquery.json
├── jquery-idletimer.sln
├── jquery-idletimer.v12.suo
├── libs
├── jquery-loader.js
├── jquery
│ └── jquery.js
└── qunit
│ ├── qunit.css
│ └── qunit.js
├── package-lock.json
├── package.json
├── src
├── .jshintrc
└── idle-timer.js
└── test
├── .jshintrc
├── idle-timer.html
└── idle-timer_test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/*
2 | build/*
3 | yarn-error.log
4 | yarn.lock
5 | undefined/coverage.tmp
6 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "curly": true,
3 | "eqeqeq": true,
4 | "immed": true,
5 | "latedef": true,
6 | "newcap": true,
7 | "noarg": true,
8 | "sub": true,
9 | "undef": true,
10 | "unused": true,
11 | "boss": true,
12 | "eqnull": true,
13 | "node": true,
14 | "quotmark": "double"
15 | }
16 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /node_modules/
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - "0.10"
5 | before_install:
6 | - npm install -g grunt-cli
7 | install:
8 | - npm install
9 | before_script:
10 | - grunt
11 | script:
12 | - grunt coveralls
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ####VERSION: 1.1.0
2 | ####RELEASED: 03/10/2014
3 | ####AUTHOR: TODD HORST
4 | -------
5 |
6 | This is the first release I'm in charge of, and as such, I've made the project my own. Hopefully things work well, and we can
7 | keep this project evolving. Please feel free to submit requests for feature.
8 |
9 | #####SRC
10 |
11 | Fixed:
12 | * if users set idle=true and left startImmediately=true ( the default ), it would toggle incorrectly
13 | * opts references (changed to obj) in toggleIdleState
14 | * chaining on all functions
15 | * mousemove issues experienced in chrome & iOS7 #4
16 | * every time you called a function (say getElapsedTime), it would reset olddate, so you were getting elapsed from last getElapsedTime, not actual time from last state change
17 | * can now call functions on default binding ex $.idleTimer("pause");
18 | * can now call default binding with parameter $.idleTimer({idle:true});
19 | * destroy doesnt remove bindings user added, only internally bound events
20 |
21 | Added:
22 | * reset, pause/resume #19
23 | * getRemainingTime, getLastActiveTime (supports autologout demo), isIdle (state of object)
24 | * internally documentation for obj keys
25 | * element, trigger event, and (copy of) object are parameters to raised idle/active event
26 | * `wheel` event. wheel is to replace DOMMouseScroll & mousewheel. We could remove DOMMouseScroll now as its technically not needed to support firefox n-1. mousewheel will stick around until we drop ie8.
27 | * `MSPointerDown` `MSPointerMove` events #22
28 | * ability to send only settings parameter
29 | * Ability to sync timer state across browser tabs
30 |
31 | Update:
32 | * changed $().data() to jQuery.data() for speed
33 | * removed myelem in toggleIdleState and replaced with elem
34 |
35 |
36 | ###Breaking Changes
37 |
38 | NOTE:
39 | I realize these changes could upset some people. If you need something added back, please open a ticket. If its determined that
40 | these are necessary, I will be happy to put them back. They were removed to clean up the code or fix bugs. You can of course continue
41 | using the old version.
42 |
43 | * Passing timeout AND settings is no longer valid. Example: `$( document ).idleTimer(3000, {idle:true});` Change to `$( document ).idleTimer({timeout:3000,idle:true});`
44 | * Using `$( document ).data("idleTimer");` returned a string. This is less ideal. Start using `$( document ).idleTimer("isIdle");`
45 | to get a boolean value of the current state of the element. If you need the string use:
46 | `var state = $( document ).idleTimer("isIdle") ? "idle" : "active"`
47 | * `Enabled` param has been removed. If needed dont initialize idleTimer until you need it. Previously there was no way to enable
48 | once it was disabled anyway, unless manually modifying the internal data. You may also want to look at reset (resets data/state without removing
49 | bindings) and pause (stops timer until resumed)
50 | * `StartImmediately` param has been removed. If you need to not have the timer start set `idle` setting to true. This was redundant and
51 | could cause a bug if users didn't flip both `idle` and `startImmediately`
52 | * Firefox lateness bug fix, Firefox has updated their implementation, so there is no need to have added code to support intended
53 | browsers. Besides I always look at elem instead of local instance on myelem now
54 | * Chrome "alert triggers event" bugfix, I believe Chrome has fixed this, if you still experience the issue let me know and I'll put it back
55 | but I was unable to reproduce this
56 |
57 |
58 |
59 | ###DEMO
60 |
61 | * Updated jQuery to newest (1.11.0)
62 | * Remove jQuery UI (was used for dialog)
63 | * Added bootstrap and standard template
64 | * Added examples of all functions
65 | * Made clearer which log was for document/textarea idletimer
66 | * Stops event propagation on textarea
67 | * Shows default state according to obj idle value
68 | * Added demo for autologout (handles that fact that js gets paused when iOS app gets minimized)
69 | * Added demo with all autobinding
70 |
71 | ###README
72 |
73 | * Link to demo
74 | * Document new functions
75 | * Document supported browsers
76 | * Document jQuery dependency
77 | * Document author history
78 | * Removed note about mixing `$.idleTimer` and `$( document ).idleTimer(...)`, related bugs have been fixed
79 | * General cleanup
80 |
81 | ###DIST
82 |
83 | * Automated builds from travis
84 | * Grunt settings have been updated, so that it builds correctly
85 | * Tests added for new functions, admittedly Im still learning this
86 | * Tests only keydown. Need to test idleTimer not the browser events. Having them all in a loop was unpredictable.
87 |
88 | ###THOUGHTS
89 |
90 | I thought about allowing users to send a callback function in, ala most jquery methods. However
91 | after researching and thinking the callbacks would be synchronous and events are async. So we
92 | will be sticking with the current method
93 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | ## Important notes
4 | Please don't edit files in the `dist` subdirectory as they are generated via grunt. You'll find source code in the `src` subdirectory!
5 |
6 | ### Code style
7 | Regarding code style like indentation and whitespace, **follow the conventions you see used in the source already.**
8 |
9 | ### PhantomJS
10 | While grunt can run the included unit tests via [PhantomJS](http://phantomjs.org/), this shouldn't be considered a substitute for the real thing. Please be sure to test the `test/*.html` unit test file(s) in _actual_ browsers.
11 |
12 | See the [Why does grunt complain that PhantomJS isn't installed?](https://github.com/gruntjs/grunt/blob/master/docs/faq.md#why-does-grunt-complain-that-phantomjs-isnt-installed) guide in the [Grunt FAQ](https://github.com/gruntjs/grunt/blob/master/docs/faq.md) for help with installing or troubleshooting PhantomJS.
13 |
14 | ## Modifying the code
15 | First, ensure that you have the latest [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) installed.
16 |
17 | Test that grunt is installed globally by running `grunt --version` at the command-line. If grunt isn't installed globally, run `npm install -g grunt` to install the latest version. _You may need to run `sudo npm install -g grunt`._
18 |
19 | _Note that in Windows, you may have to run `grunt.cmd` instead of `grunt`._
20 |
21 | 1. Fork and clone the repo.
22 | 1. Run `npm install` to install all dependencies (including grunt).
23 | 1. Run `grunt` to grunt this project.
24 |
25 | Assuming that you don't see any red, you're ready to go. Just be sure to run `grunt` after making any changes, to ensure that nothing is broken.
26 |
27 | ## Submitting pull requests
28 |
29 | 1. Create a new branch, please don't work in your `master` branch directly.
30 | 1. Add failing tests for the change you want to make. Run `grunt` to see the tests fail.
31 | 1. Fix stuff.
32 | 1. Run `grunt` to see if the tests pass. Repeat steps 2-4 until done.
33 | 1. Open `test/*.html` unit test file(s) in actual browser to ensure tests pass everywhere.
34 | 1. Update the documentation to reflect any changes.
35 | 1. Push to your fork and submit a pull request.
36 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | module.exports = function(grunt) {
4 |
5 | // Project configuration.
6 | grunt.initConfig({
7 | // Metadata.
8 | pkg: grunt.file.readJSON("idle-timer.jquery.json"),
9 | banner: "/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - " +
10 | "<%= grunt.template.today('yyyy-mm-dd') %>\n" +
11 | "<%= pkg.homepage ? '* ' + pkg.homepage + '\\n' : '' %>" +
12 | "* Copyright (c) <%= grunt.template.today('yyyy') %> <%= pkg.author.name %>;" +
13 | " Licensed <%= pkg.licenses.map(o => o['type']).join(', ') %> */\n",
14 | minbanner: "/*! <%= pkg.title || pkg.name %> v<%= pkg.version %> <%= grunt.template.today('yyyy-mm-dd') %> | " +
15 | "<%= pkg.homepage ? pkg.homepage : '' %> | (c) <%= grunt.template.today('yyyy') %> <%= pkg.author.name %> | " +
16 | "Licensed <%= pkg.licenses.map(o => o['type']).join(', ') %> */\n",
17 | // Task configuration.
18 | concat: {
19 | options: {
20 | banner: "<%= banner %>",
21 | stripBanners: true
22 | },
23 | dist: {
24 | files: [
25 | {
26 | src: ["src/<%= pkg.name %>.js"],
27 | dest: "dist/<%= pkg.name %>.js"
28 | },
29 | {
30 | src: ["src/<%= pkg.name %>.js"],
31 | dest: "dist/<%= pkg.name %>.<%= pkg.version %>.js"
32 | }
33 | ]
34 | },
35 | },
36 | uglify: {
37 | options: {
38 | banner: "<%= minbanner %>"
39 | },
40 | dist: {
41 | files: [
42 | {
43 | src: "<%= concat.dist.files[0].dest %>",
44 | dest: "dist/<%= pkg.name %>.min.js"
45 | },
46 | {
47 | src: "<%= concat.dist.files[0].dest %>",
48 | dest: "dist/<%= pkg.name %>.<%= pkg.version %>.min.js"
49 | }
50 | ]
51 | },
52 | },
53 | qunit: {
54 | all: {
55 | options: {
56 | urls:["test/idle-timer.html"]
57 | }
58 | }
59 | },
60 | coveralls: {
61 | options: {
62 | // dont fail if coveralls fails
63 | force: true
64 | },
65 | main_target: {
66 | src: "build/report/lcov/lcov.info"
67 | }
68 | },
69 | jshint: {
70 | gruntfile: {
71 | options: {
72 | jshintrc: ".jshintrc",
73 | reporterOutput: ""
74 | },
75 | src: "Gruntfile.js"
76 | },
77 | src: {
78 | options: {
79 | jshintrc: "src/.jshintrc",
80 | reporterOutput: ""
81 | },
82 | src: ["src/**/*.js"]
83 | },
84 | test: {
85 | options: {
86 | jshintrc: "test/.jshintrc",
87 | reporterOutput: ""
88 | },
89 | src: ["test/**/*.js"]
90 | },
91 | },
92 | watch: {
93 | gruntfile: {
94 | files: "<%= jshint.gruntfile.src %>",
95 | tasks: ["jshint:gruntfile"]
96 | },
97 | src: {
98 | files: "<%= jshint.src.src %>",
99 | tasks: ["jshint:src", "qunit"]
100 | },
101 | test: {
102 | files: "<%= jshint.test.src %>",
103 | tasks: ["jshint:test", "qunit"]
104 | },
105 | },
106 | });
107 |
108 | // These plugins provide necessary tasks.
109 | grunt.loadNpmTasks("grunt-contrib-jshint");
110 | grunt.loadNpmTasks("grunt-coveralls");
111 | grunt.loadNpmTasks("grunt-contrib-qunit");
112 | grunt.loadNpmTasks("grunt-contrib-concat");
113 | grunt.loadNpmTasks("grunt-contrib-uglify");
114 | grunt.loadNpmTasks("grunt-contrib-watch");
115 |
116 | // Default task.
117 | grunt.registerTask("default", ["jshint", "qunit", "concat", "uglify"]);
118 |
119 | };
120 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 Paul Irish
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | jQuery Idle Timer Plugin
2 | ========================
3 |
4 | [](https://travis-ci.org/thorst/jquery-idletimer)
5 | [](https://david-dm.org/thorst/jquery-idletimer)
6 | [](https://david-dm.org/thorst/jquery-idletimer#info=devDependencies)
7 | [](https://coveralls.io/r/thorst/jquery-idletimer?branch=master)
8 |
9 | Demo
10 | --------
11 | https://thorst.github.io/jquery-idletimer/index.html
12 |
13 | Download
14 | --------
15 | * [Compressed ~3kb](https://raw.github.com/thorst/jquery-idletimer/master/dist/idle-timer.min.js)
16 | * [Uncompressed ~11kb](https://raw.github.com/thorst/jquery-idletimer/master/dist/idle-timer.js)
17 |
18 | Purpose
19 | -------
20 |
21 | Fires a custom event when the user is "idle". Idle is defined by not...
22 |
23 | * moving the mouse
24 | * scrolling the mouse wheel
25 | * using the keyboard
26 |
27 |
28 | Usage
29 | -----
30 |
31 | There are two ways to instantiate. Either statically, or on an element. Element bound timers
32 | will only watch for events inside of them. You may just want page-level activity, in which
33 | case you may set up your timers on `document`, `document.documentElement`, and `document.body`.
34 | Instantiate returns jQuery for chaining.
35 |
36 | ```javascript
37 | $(function() {
38 | // binds to document - shorthand
39 | $.idleTimer();
40 |
41 | // binds to document - explicit
42 | $( document ).idleTimer();
43 |
44 | // bind to different element
45 | $( "#myTextArea" ).idleTimer();
46 | });
47 | ```
48 |
49 | Options
50 | -----
51 | You can configure the settings several ways
52 |
53 | ```javascript
54 | $(function() {
55 | // idleTimer() with all defaults
56 | $( document ).idleTimer( );
57 |
58 | // idleTimer() takes an optional numeric argument that defines just the idle timeout
59 | // timeout is in milliseconds
60 | $( document ).idleTimer( 10000 );
61 |
62 | // idleTimer() takes an optional object argument that defines any/all setting
63 | $( document ).idleTimer( {
64 | timeout:10000,
65 | idle:true
66 | });
67 |
68 | /*
69 | * Here are the possible settings
70 | * you can omit any or all of them
71 | */
72 |
73 | // indicates if the user is idle
74 | idle [default:false]
75 |
76 | // the timeout period
77 | timeout [default:30000]
78 |
79 | // activity is any one of these events
80 | events [default:'mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove']
81 |
82 | // If set, the use a localStorage key to sync activity across browser tabs/windows
83 | timerSyncId [default:null]
84 | });
85 | ```
86 |
87 | Events
88 | -----
89 | When a users state changes a custom events get triggered. There are several parameters
90 | passed to your handler for you to use.
91 |
92 | ```javascript
93 | $(function() {
94 | $( document ).on( "idle.idleTimer", function(event, elem, obj){
95 | // function you want to fire when the user goes idle
96 | });
97 |
98 | $( document ).on( "active.idleTimer", function(event, elem, obj, triggerevent){
99 | // function you want to fire when the user becomes active again
100 | });
101 |
102 | /*
103 | * Here are the arguments
104 | */
105 | // event
106 | // will be either idle.idleTimer or active.idleTimer
107 | // use event.stopPropagation(); to stop element from bubbling up to document
108 |
109 | // elem
110 | // is the element that the event was triggered on
111 |
112 | // obj
113 | // is a copy of the internal data used by idleTimer
114 |
115 | // triggerevent
116 | // is the initial event that triggered the element to become active
117 | // obviously for idle state this will be undefined
118 | });
119 | ```
120 |
121 | Methods
122 | -----
123 | There are several methods to invoke
124 |
125 | ```javascript
126 | $(function() {
127 | // stop the timer, removes data, removes event bindings
128 | // to come back from this you will need to instantiate again
129 | // returns: jQuery
130 | $( document ).idleTimer("destroy");
131 |
132 | // save remaining time, and stops the timer
133 | // returns: jQuery
134 | $( document ).idleTimer("pause");
135 |
136 | // starts timer with remaining time
137 | // returns: jQuery
138 | $( document ).idleTimer("resume");
139 |
140 | // restore initial idle state, and restart the timer
141 | // returns: jQuery
142 | $( document ).idleTimer("reset");
143 |
144 | // get time left until idle, if idle return 0
145 | // returns: number
146 | $( document ).idleTimer("getRemainingTime");
147 |
148 | // get time elapsed (in ms) since the user went idle/active
149 | // if idle, how have you been idle, if active, how long have you been active
150 | // returns: number
151 | $( document ).idleTimer("getElapsedTime");
152 |
153 | // get time last active event fired
154 | // returns: number
155 | $( document ).idleTimer("getLastActiveTime");
156 |
157 | // you can also query if it's "idle" or "active"
158 | // returns: bool
159 | $( document ).idleTimer("isIdle");
160 | });
161 | ```
162 | Using multiple idle monitors
163 | -----
164 | When using multiple idle monitors on the same element, a unique id needs be used for each one.
165 |
166 | ####Options
167 | ```javascript
168 | $(function() {
169 | // idleTimer() takes an optional string argument that allows using multiple timers on the same element
170 | $( document ).idleTimer( 10000, "someUniqueId" );
171 | // equivalent
172 | $.idleTimer(10000, document, "someUniqueId");
173 | });
174 | ```
175 | ####Methods
176 | ```javascript
177 | $(function() {
178 | var uniqueId = "someUniqueString";
179 | $( document ).idleTimer("pause", uniqueId); // same for other methods like destroy, reset, ...
180 | });
181 | ```
182 | ####Events
183 | ```javascript
184 | $(function() {
185 | var uniqueId = "someUniqueString";
186 | $( document ).on( "idle.idleTimer" + uniqueId, function(event, elem, obj){ // same for the active event
187 | // function you want to fire for the idle timer with matching unique id on that element
188 | });
189 | });
190 | ```
191 | Pre-Req
192 | -------
193 | jQuery 1.7 (tested with 1.11.0)
194 |
195 | Intended Browser Support
196 | -------
197 | ####Desktop
198 | * >=IE8
199 | * Firefox n-1
200 | * Chrome n-1
201 | * Safari n
202 |
203 | ####Mobile
204 | * iOS n-1
205 | * Android (version?)
206 | * Windows Phone IEMobile/10.0
207 |
208 | Links
209 | -------
210 | * [jQuery plugin repo listing](http://plugins.jquery.com/idle-timer/)
211 | * [cdn](http://cdnjs.com/libraries/jquery-idletimer/)
212 | * [nuget]() - coming soon
213 | * [Eric Hynds Idle Timeout plugin](https://github.com/ehynds/jquery-idle-timeout)
214 | (note we have similar functionality [here](http://thorst.github.io/jquery-idletimer/prod/demos/autologout.html))
215 |
216 | Playground
217 | -------
218 | * [js fiddle](http://jsfiddle.net/thorst/2aGL4/)
219 | * [css deck](http://cssdeck.com/labs/sosoro3m)
220 |
221 | Version History
222 | -------
223 | | Version | Author | Released | Links |
224 | | --------------------------------------- |-----------------| ---------- | ----------------------------- |
225 | | [1.0.0](https://raw.github.com/thorst/jquery-idletimer/master/dist/idle-timer.1.0.0.min.js) | Todd Horst | 03/10/2014 | [Change Log](CHANGELOG.md) - [Breaking Changes](CHANGELOG.md#breaking-changes) |
226 | | [0.9.3](https://raw.github.com/thorst/jquery-idletimer/master/dist/idle-timer.0.9.3.min.js) | Mike Sherov | 08/04/2013 |
227 |
228 |
229 | Author History
230 | -------
231 | * Nicholas C. Zakas (yui Version) [idleTimer Blog](http://www.nczonline.net/blog/2009/06/02/detecting-if-the-user-is-idle-with-javascript-and-yui-3/) | [Github Profile](https://github.com/nzakas) | [Github](https://github.com/nzakas/jstools/)
232 | * Paul Irish (initial jQuery Version) [idleTimer Blog](http://paulirish.com/2009/jquery-idletimer-plugin/) | [Github Profile](https://github.com/paulirish) | [Github](https://github.com/paulirish/jquery-idletimer/)
233 | * Mike Sherov (transfered from Paul) [Github Profile](https://github.com/mikesherov)
234 | * Todd Horst (transfered from Mike) [Github Profile](https://github.com/thorst)
235 |
236 | Bug?
237 | -------
238 | Please create a [fiddle](http://jsfiddle.net/thorst/2aGL4/4/) and [submit a ticket](https://github.com/thorst/jquery-idletimer/issues/new)
239 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery-idletimer",
3 | "homepage": "http://thorst.github.io/jquery-idletimer",
4 | "authors": [
5 | "Todd Horst"
6 | ],
7 | "description": "Provides you a way to monitor user activity with a page",
8 | "main": "src/idle-timer.js",
9 | "moduleType": [
10 | "globals"
11 | ],
12 | "keywords": [
13 | "idle",
14 | "timer",
15 | "inactive"
16 | ],
17 | "license": "MIT",
18 | "ignore": [
19 | "**/.*",
20 | "node_modules",
21 | "bower_components",
22 | "test",
23 | "tests"
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/demos/autologout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Jquery-idletimer
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
34 |
35 |
36 |
63 |
64 |
Concept
65 |
66 | Wait 10 seconds, you will see a expiring warning. Wait 10 more seconds and you will see that you have been logged out.
67 |
68 |
69 | In the real world I forward them to the logout url, which intern fowards them to login screen, instead of showing the 2nd dialog.
70 | You can modify the session.logout function.
71 |
72 |
73 | We could use the active.idleTimer event to clearTimeout, however I prefer the user to explicitly say they want to keep the
74 | session open by clicking ok, not just moving the mouse on the screen.
75 |
76 |
77 | This demo takes into account when a mobile device closes the browser, and after the idle timeout expires, launches the browser again. Instead
78 | of displaying the warning, it will jump straight to the logged out dialog.
79 |
80 |
81 | For the sake of complete demo, I've included the code needed to call a keepalive url to keep the server side session valid.
82 |
83 |
84 |
85 |
86 |
87 |
90 |
91 |
You've been inactive for a while. For your security, we'll log you out automatically. Click "Stay Online" to continue your session.
92 |
Your session will expire in 120 seconds.
93 |
94 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
107 |
108 |
Your session has expired.
109 |
110 |
112 |
113 |
114 |
115 |
187 |
188 |
189 |
--------------------------------------------------------------------------------
/demos/autologoutsync.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Jquery-idletimer
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
26 |
27 |
28 |
29 |
30 | Jquery-idletimer
31 |
32 |
33 |
34 |
35 |
49 |
50 |
51 |
Concept
52 |
53 | Wait 10 seconds, you will see a expiring warning. Wait 10 more seconds and you will see that you have been logged out.
54 |
55 |
56 | In the real world I forward them to the logout url, which intern fowards them to login screen, instead of showing the 2nd dialog. You can modify the app.session.logout function.
57 |
58 |
59 | We could use the active.idleTimer event to clearTimeout, however I prefer the user to explicitly say they want to keep the session open by clicking ok, not just moving the mouse on the screen.
60 |
61 |
62 | This demo takes into account when a mobile device closes the browser, and after the idle timeout expires, launches the browser again. Instead of displaying the warning, it will jump straight to the logged out dialog.
63 |
64 |
65 | For this demo we've enabled localStorage to sync accross tabs of the same browser. This will keep the client side happy, but we still need a keepAlive service to keep the server side session active.
66 |
67 |
68 | For the sake of complete demo, I've included the code needed to call a keepalive url to keep the server side session valid.
69 |
70 |
71 |
72 |
73 |
74 |
78 |
79 |
You've been inactive for a while. For your security, we'll log you out automatically. Click "Stay Online" to continue your session.
80 |
Your session will expire in 120 seconds.
81 |
82 |
83 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
98 |
99 |
Your session has expired.
100 |
101 |
102 |
103 |
104 |
105 |
248 |
249 |
250 |
251 |
--------------------------------------------------------------------------------
/demos/defaultbinding.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Jquery-idletimer
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
35 |
36 |
37 |
38 |
64 |
65 |
66 |
67 |
Concept
68 |
Here we use default bindings. Instead of explicitly telling idleTimer which element to bind to, it assumes document.
69 |
Some previous versions had issues mixing default binding with explicit calling on document.
70 |
This should no longer be the case. To test I've added 2 sets of buttons to show that they can be mixed.
71 |
The background color changes to show that it is returning a jQuery object
72 |
73 |
74 |
75 |
Document second timeout
76 |
default binding
77 |
89 |
explicit binding
90 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
127 |
128 |
188 |
189 |
321 |
322 |
453 |
454 |
455 |
456 |
457 |
--------------------------------------------------------------------------------
/demos/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Jquery-idletimer
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
34 |
35 |
36 |
62 |
63 |
Concept
64 |
The idle timer is built on jQuery and provides two events: idle.idleTimer
and active.idleTimer
, which fire when the user's idle state has changed.
65 |
When you move your mouse over the page or start typing, you're considered "active".
66 |
On this page we have two idle timers. One for the entire document. Another for the text area on the right (or bottom if your on mobile).
67 |
I use explicit instantiation here
68 |
69 |
70 |
Document second timeout
71 |
78 |
79 |
80 |
81 |
Element second timeout
82 |
88 |
89 |
90 |
91 |
Dialogs
92 |
93 |
94 | Launch modal
95 |
96 |
97 | Launch alert
98 |
99 |
100 |
101 |
102 |
103 |
107 |
108 | ...
109 |
110 |
113 |
114 |
115 |
116 |
117 |
135 |
271 |
272 |
394 |
395 |
396 |
--------------------------------------------------------------------------------
/demos/respond.proxy.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thorst/jquery-idletimer/d52354c25ff688fe16550338bbac9c69218b1326/demos/respond.proxy.gif
--------------------------------------------------------------------------------
/demos/respond.proxy.js:
--------------------------------------------------------------------------------
1 | /*! Respond.js: min/max-width media query polyfill. Remote proxy (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */
2 | (function(win, doc, undefined){
3 | var docElem = doc.documentElement,
4 | proxyURL = doc.getElementById("respond-proxy").href,
5 | redirectURL = (doc.getElementById("respond-redirect") || location).href,
6 | baseElem = doc.getElementsByTagName("base")[0],
7 | urls = [],
8 | refNode;
9 |
10 | function encode(url){
11 | return win.encodeURIComponent(url);
12 | }
13 |
14 | function fakejax( url, callback ){
15 |
16 | var iframe,
17 | AXO;
18 |
19 | // All hail Google http://j.mp/iKMI19
20 | // Behold, an iframe proxy without annoying clicky noises.
21 | if ( "ActiveXObject" in win ) {
22 | AXO = new ActiveXObject( "htmlfile" );
23 | AXO.open();
24 | AXO.write( '' );
25 | AXO.close();
26 | iframe = AXO.getElementById( "x" );
27 | } else {
28 | iframe = doc.createElement( "iframe" );
29 | iframe.style.cssText = "position:absolute;top:-99em";
30 | docElem.insertBefore(iframe, docElem.firstElementChild || docElem.firstChild );
31 | }
32 |
33 | iframe.src = checkBaseURL(proxyURL) + "?url=" + encode(redirectURL) + "&css=" + encode(checkBaseURL(url));
34 |
35 | function checkFrameName() {
36 | var cssText;
37 |
38 | try {
39 | cssText = iframe.contentWindow.name;
40 | }
41 | catch (e) { }
42 |
43 | if (cssText) {
44 | // We've got what we need. Stop the iframe from loading further content.
45 | iframe.src = "about:blank";
46 | iframe.parentNode.removeChild(iframe);
47 | iframe = null;
48 |
49 |
50 | // Per http://j.mp/kn9EPh, not taking any chances. Flushing the ActiveXObject
51 | if (AXO) {
52 | AXO = null;
53 |
54 | if (win.CollectGarbage) {
55 | win.CollectGarbage();
56 | }
57 | }
58 |
59 | callback(cssText);
60 | }
61 | else{
62 | win.setTimeout(checkFrameName, 100);
63 | }
64 | }
65 |
66 | win.setTimeout(checkFrameName, 500);
67 | }
68 |
69 | // http://stackoverflow.com/a/472729
70 | function checkBaseURL(href) {
71 | var el = document.createElement('div'),
72 | escapedURL = href.split('&').join('&').
73 | split('<').join('<').
74 | split('"').join('"');
75 |
76 | el.innerHTML = 'x ';
77 | return el.firstChild.href;
78 | }
79 |
80 | function checkRedirectURL() {
81 | // IE6 & IE7 don't build out absolute urls in attributes.
82 | // So respond.proxy.gif remains relative instead of http://example.com/respond.proxy.gif.
83 | // This trickery resolves that issue.
84 | if (~ !redirectURL.indexOf(location.host)) {
85 |
86 | var fakeLink = doc.createElement("div");
87 |
88 | fakeLink.innerHTML = ' ';
89 | docElem.insertBefore(fakeLink, docElem.firstElementChild || docElem.firstChild );
90 |
91 | // Grab the parsed URL from that dummy object
92 | redirectURL = fakeLink.firstChild.href;
93 |
94 | // Clean up
95 | fakeLink.parentNode.removeChild(fakeLink);
96 | fakeLink = null;
97 | }
98 | }
99 |
100 | function buildUrls(){
101 | var links = doc.getElementsByTagName( "link" );
102 |
103 | for( var i = 0, linkl = links.length; i < linkl; i++ ){
104 |
105 | var thislink = links[i],
106 | href = links[i].href,
107 | extreg = (/^([a-zA-Z:]*\/\/(www\.)?)/).test( href ),
108 | ext = (baseElem && !extreg) || extreg;
109 |
110 | //make sure it's an external stylesheet
111 | if( thislink.rel.indexOf( "stylesheet" ) >= 0 && ext ){
112 | (function( link ){
113 | fakejax( href, function( css ){
114 | link.styleSheet.rawCssText = css;
115 | respond.update();
116 | } );
117 | })( thislink );
118 | }
119 | }
120 |
121 |
122 | }
123 |
124 | if( !respond.mediaQueriesSupported ){
125 | checkRedirectURL();
126 | buildUrls();
127 | }
128 |
129 | })( window, document );
130 |
--------------------------------------------------------------------------------
/dist/idle-timer.0.9.3.js:
--------------------------------------------------------------------------------
1 | /*! Idle Timer - v0.9.2 - 2013-08-04
2 | * https://github.com/mikesherov/jquery-idletimer
3 | * Copyright (c) 2013 Paul Irish; Licensed MIT */
4 | ( function( $ ) {
5 |
6 | $.idleTimer = function( firstParam, elem, opts ) {
7 |
8 | // defaults that are to be stored as instance props on the elem
9 | opts = $.extend( {
10 | startImmediately: true, //starts a timeout as soon as the timer is set up
11 | idle: false, //indicates if the user is idle
12 | enabled: true, //indicates if the idle timer is enabled
13 | timeout: 30000, //the amount of time (ms) before the user is considered idle
14 | events: "mousemove keydown DOMMouseScroll mousewheel mousedown touchstart touchmove" // activity is one of these events
15 | }, opts );
16 |
17 |
18 | elem = elem || document;
19 |
20 | var jqElem = $( elem ),
21 | obj = jqElem.data("idleTimerObj") || {},
22 |
23 | /* (intentionally not documented)
24 | * Toggles the idle state and fires an appropriate event.
25 | * @return {void}
26 | */
27 | toggleIdleState = function( myelem ) {
28 |
29 | // curse you, mozilla setTimeout lateness bug!
30 | if ( typeof myelem === "number" ) {
31 | myelem = undefined;
32 | }
33 |
34 | var obj = $.data( myelem || elem, "idleTimerObj" );
35 |
36 | //toggle the state
37 | obj.idle = !obj.idle;
38 |
39 | // reset timeout
40 | var elapsed = ( +new Date() ) - obj.olddate;
41 | obj.olddate = +new Date();
42 |
43 | // handle Chrome always triggering idle after js alert or comfirm popup
44 | if ( obj.idle && ( elapsed < opts.timeout ) ) {
45 | obj.idle = false;
46 | clearTimeout( $.idleTimer.tId );
47 | if ( opts.enabled ) {
48 | $.idleTimer.tId = setTimeout( toggleIdleState, opts.timeout );
49 | }
50 | return;
51 | }
52 |
53 | // create a custom event, but first, store the new state on the element
54 | // and then append that string to a namespace
55 | var event = $.Event( $.data( elem, "idleTimer", obj.idle ? "idle" : "active" ) + ".idleTimer" );
56 | $( elem ).trigger( event );
57 | },
58 |
59 | /**
60 | * Stops the idle timer. This removes appropriate event handlers
61 | * and cancels any pending timeouts.
62 | * @return {void}
63 | * @method stop
64 | * @static
65 | */
66 | stop = function( jqElem ) {
67 |
68 | var obj = jqElem.data("idleTimerObj") || {};
69 |
70 | //set to disabled
71 | obj.enabled = false;
72 |
73 | //clear any pending timeouts
74 | clearTimeout( obj.tId );
75 |
76 | //detach the event handlers
77 | jqElem.off(".idleTimer");
78 | };
79 |
80 | obj.olddate = obj.olddate || +new Date();
81 |
82 | if ( typeof firstParam === "number" ) {
83 | opts.timeout = firstParam;
84 | } else if ( firstParam === "destroy" ) {
85 | stop( jqElem );
86 | return this;
87 | } else if ( firstParam === "getElapsedTime" ) {
88 | return ( +new Date() ) - obj.olddate;
89 | }
90 |
91 |
92 | /* (intentionally not documented)
93 | * Handles a user event indicating that the user isn't idle.
94 | * @param {Event} event A DOM2-normalized event object.
95 | * @return {void}
96 | */
97 | jqElem.on( $.trim( ( opts.events + " " ).split(" ").join(".idleTimer ") ), function() {
98 | var obj = $.data( this, "idleTimerObj" );
99 |
100 | //clear any existing timeout
101 | clearTimeout( obj.tId );
102 |
103 | //if the idle timer is enabled
104 | if ( obj.enabled ){
105 | //if it's idle, that means the user is no longer idle
106 | if ( obj.idle ){
107 | toggleIdleState( this );
108 | }
109 |
110 | //set a new timeout
111 | obj.tId = setTimeout( toggleIdleState, obj.timeout );
112 | }
113 | });
114 |
115 | obj.idle = opts.idle;
116 | obj.enabled = opts.enabled;
117 | obj.timeout = opts.timeout;
118 |
119 | //set a timeout to toggle state. May wish to omit this in some situations
120 | if ( opts.startImmediately ) {
121 | obj.tId = setTimeout( toggleIdleState, obj.timeout );
122 | }
123 |
124 | // assume the user is active for the first x seconds.
125 | jqElem.data( "idleTimer", "active" );
126 |
127 | // store our instance on the object
128 | jqElem.data( "idleTimerObj", obj );
129 | };
130 |
131 | $.fn.idleTimer = function( firstParam, opts ) {
132 | // Allow omission of opts for backward compatibility
133 | if ( !opts ) {
134 | opts = {};
135 | }
136 |
137 | if ( this[0] ){
138 | return $.idleTimer( firstParam, this[0], opts );
139 | }
140 |
141 | return this;
142 | };
143 |
144 | })( jQuery );
145 |
--------------------------------------------------------------------------------
/dist/idle-timer.0.9.3.min.js:
--------------------------------------------------------------------------------
1 | /*! Idle Timer - v0.9.2 - 2013-08-04
2 | * https://github.com/mikesherov/jquery-idletimer
3 | * Copyright (c) 2013 Paul Irish; Licensed MIT */
4 | (function(e){e.idleTimer=function(t,i,d){d=e.extend({startImmediately:!0,idle:!1,enabled:!0,timeout:3e4,events:"mousemove keydown DOMMouseScroll mousewheel mousedown touchstart touchmove"},d),i=i||document;var l=e(i),a=l.data("idleTimerObj")||{},o=function(t){"number"==typeof t&&(t=void 0);var l=e.data(t||i,"idleTimerObj");l.idle=!l.idle;var a=+new Date-l.olddate;if(l.olddate=+new Date,l.idle&&d.timeout>a)return l.idle=!1,clearTimeout(e.idleTimer.tId),d.enabled&&(e.idleTimer.tId=setTimeout(o,d.timeout)),void 0;var m=e.Event(e.data(i,"idleTimer",l.idle?"idle":"active")+".idleTimer");e(i).trigger(m)},m=function(e){var t=e.data("idleTimerObj")||{};t.enabled=!1,clearTimeout(t.tId),e.off(".idleTimer")};if(a.olddate=a.olddate||+new Date,"number"==typeof t)d.timeout=t;else{if("destroy"===t)return m(l),this;if("getElapsedTime"===t)return+new Date-a.olddate}l.on(e.trim((d.events+" ").split(" ").join(".idleTimer ")),function(){var t=e.data(this,"idleTimerObj");clearTimeout(t.tId),t.enabled&&(t.idle&&o(this),t.tId=setTimeout(o,t.timeout))}),a.idle=d.idle,a.enabled=d.enabled,a.timeout=d.timeout,d.startImmediately&&(a.tId=setTimeout(o,a.timeout)),l.data("idleTimer","active"),l.data("idleTimerObj",a)},e.fn.idleTimer=function(t,i){return i||(i={}),this[0]?e.idleTimer(t,this[0],i):this}})(jQuery);
--------------------------------------------------------------------------------
/dist/idle-timer.1.0.0.js:
--------------------------------------------------------------------------------
1 | /*! Idle Timer - v1.0.0 - 2014-03-10
2 | * https://github.com/thorst/jquery-idletimer
3 | * Copyright (c) 2014 Paul Irish; Licensed MIT */
4 | /*
5 | mousewheel (deprecated) -> IE6.0, Chrome, Opera, Safari
6 | DOMMouseScroll (deprecated) -> Firefox 1.0
7 | wheel (standard) -> Chrome 31, Firefox 17, IE9, Firefox Mobile 17.0
8 |
9 | //No need to use, use DOMMouseScroll
10 | MozMousePixelScroll -> Firefox 3.5, Firefox Mobile 1.0
11 |
12 | //Events
13 | WheelEvent -> see wheel
14 | MouseWheelEvent -> see mousewheel
15 | MouseScrollEvent -> Firefox 3.5, Firefox Mobile 1.0
16 | */
17 | (function ($) {
18 |
19 | $.idleTimer = function (firstParam, elem) {
20 | var opts;
21 | if ( typeof firstParam === "object" ) {
22 | opts = firstParam;
23 | firstParam = null;
24 | } else if (typeof firstParam === "number") {
25 | opts = { timeout: firstParam };
26 | firstParam = null;
27 | }
28 |
29 | // element to watch
30 | elem = elem || document;
31 |
32 | // defaults that are to be stored as instance props on the elem
33 | opts = $.extend({
34 | idle: false, // indicates if the user is idle
35 | timeout: 30000, // the amount of time (ms) before the user is considered idle
36 | events: "mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove" // define active events
37 | }, opts);
38 |
39 | var jqElem = $(elem),
40 | obj = jqElem.data("idleTimerObj") || {},
41 |
42 | /* (intentionally not documented)
43 | * Toggles the idle state and fires an appropriate event.
44 | * @return {void}
45 | */
46 | toggleIdleState = function (e) {
47 |
48 | var obj = $.data(elem, "idleTimerObj") || {};
49 |
50 | // toggle the state
51 | obj.idle = !obj.idle;
52 |
53 | // store toggle state date time
54 | obj.olddate = +new Date();
55 |
56 | // create a custom event, with state and name space
57 | var event = $.Event((obj.idle ? "idle" : "active") + ".idleTimer");
58 |
59 | // trigger event on object with elem and copy of obj
60 | $(elem).trigger(event, [elem, $.extend({}, obj), e]);
61 | },
62 | /**
63 | * Handle event triggers
64 | * @return {void}
65 | * @method event
66 | * @static
67 | */
68 | handleEvent = function (e) {
69 |
70 | var obj = $.data(elem, "idleTimerObj") || {};
71 |
72 | // this is already paused, ignore events for now
73 | if (obj.remaining != null) { return; }
74 |
75 | /*
76 | mousemove is kinda buggy, it can be triggered when it should be idle.
77 | Typically is happening between 115 - 150 milliseconds after idle triggered.
78 | @psyafter & @kaellis report "always triggered if using modal (jQuery ui, with overlay)"
79 | @thorst has similar issues on ios7 "after $.scrollTop() on text area"
80 | */
81 | if (e.type === "mousemove") {
82 | // if coord are same, it didn't move
83 | if (e.pageX === obj.pageX && e.pageY === obj.pageY) {
84 | return;
85 | }
86 | // if coord don't exist how could it move
87 | if (typeof e.pageX === "undefined" && typeof e.pageY === "undefined") {
88 | return;
89 | }
90 | // under 200 ms is hard to do, and you would have to stop, as continuous activity will bypass this
91 | var elapsed = (+new Date()) - obj.olddate;
92 | if (elapsed < 200) {
93 | return;
94 | }
95 | }
96 |
97 | // clear any existing timeout
98 | clearTimeout(obj.tId);
99 |
100 | // if the idle timer is enabled, flip
101 | if (obj.idle) {
102 | toggleIdleState(e);
103 | }
104 |
105 | // store when user was last active
106 | obj.lastActive = +new Date();
107 |
108 | // update mouse coord
109 | obj.pageX = e.pageX;
110 | obj.pageY = e.pageY;
111 |
112 | // set a new timeout
113 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
114 |
115 | },
116 | /**
117 | * Restore initial settings and restart timer
118 | * @return {void}
119 | * @method reset
120 | * @static
121 | */
122 | reset = function () {
123 |
124 | var obj = $.data(elem, "idleTimerObj") || {};
125 |
126 | // reset settings
127 | obj.idle = obj.idleBackup;
128 | obj.olddate = +new Date();
129 | obj.lastActive = obj.olddate;
130 | obj.remaining = null;
131 |
132 | // reset Timers
133 | clearTimeout(obj.tId);
134 | if (!obj.idle) {
135 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
136 | }
137 |
138 | },
139 | /**
140 | * Store remaining time, stop timer
141 | * You can pause from an idle OR active state
142 | * @return {void}
143 | * @method pause
144 | * @static
145 | */
146 | pause = function () {
147 |
148 | var obj = $.data(elem, "idleTimerObj") || {};
149 |
150 | // this is already paused
151 | if ( obj.remaining != null ) { return; }
152 |
153 | // define how much is left on the timer
154 | obj.remaining = obj.timeout - ((+new Date()) - obj.olddate);
155 |
156 | // clear any existing timeout
157 | clearTimeout(obj.tId);
158 | },
159 | /**
160 | * Start timer with remaining value
161 | * @return {void}
162 | * @method resume
163 | * @static
164 | */
165 | resume = function () {
166 |
167 | var obj = $.data(elem, "idleTimerObj") || {};
168 |
169 | // this isn't paused yet
170 | if ( obj.remaining == null ) { return; }
171 |
172 | // start timer
173 | if ( !obj.idle ) {
174 | obj.tId = setTimeout(toggleIdleState, obj.remaining);
175 | }
176 |
177 | // clear remaining
178 | obj.remaining = null;
179 | },
180 | /**
181 | * Stops the idle timer. This removes appropriate event handlers
182 | * and cancels any pending timeouts.
183 | * @return {void}
184 | * @method destroy
185 | * @static
186 | */
187 | destroy = function () {
188 |
189 | var obj = $.data(elem, "idleTimerObj") || {};
190 |
191 | //clear any pending timeouts
192 | clearTimeout(obj.tId);
193 |
194 | //Remove data
195 | jqElem.removeData("idleTimerObj");
196 |
197 | //detach the event handlers
198 | jqElem.off("._idleTimer");
199 | },
200 | /**
201 | * Returns the time until becoming idle
202 | * @return {number}
203 | * @method remainingtime
204 | * @static
205 | */
206 | remainingtime = function () {
207 |
208 | var obj = $.data(elem, "idleTimerObj") || {};
209 |
210 | //If idle there is no time remaining
211 | if ( obj.idle ) { return 0; }
212 |
213 | //If its paused just return that
214 | if ( obj.remaining != null ) { return obj.remaining; }
215 |
216 | //Determine remaining, if negative idle didn't finish flipping, just return 0
217 | var remaining = obj.timeout - ((+new Date()) - obj.lastActive);
218 | if (remaining < 0) { remaining = 0; }
219 |
220 | //If this is paused return that number, else return current remaining
221 | return remaining;
222 | };
223 |
224 |
225 | // determine which function to call
226 | if (firstParam === null && typeof obj.idle !== "undefined") {
227 | // they think they want to init, but it already is, just reset
228 | reset();
229 | return jqElem;
230 | } else if (firstParam === null) {
231 | // they want to init
232 | } else if (firstParam !== null && typeof obj.idle === "undefined") {
233 | // they want to do something, but it isnt init
234 | // not sure the best way to handle this
235 | return false;
236 | } else if (firstParam === "destroy") {
237 | destroy();
238 | return jqElem;
239 | } else if (firstParam === "pause") {
240 | pause();
241 | return jqElem;
242 | } else if (firstParam === "resume") {
243 | resume();
244 | return jqElem;
245 | } else if (firstParam === "reset") {
246 | reset();
247 | return jqElem;
248 | } else if (firstParam === "getRemainingTime") {
249 | return remainingtime();
250 | } else if (firstParam === "getElapsedTime") {
251 | return (+new Date()) - obj.olddate;
252 | } else if (firstParam === "getLastActiveTime") {
253 | return obj.lastActive;
254 | } else if (firstParam === "isIdle") {
255 | return obj.idle;
256 | }
257 |
258 | /* (intentionally not documented)
259 | * Handles a user event indicating that the user isn't idle. namespaced with internal idleTimer
260 | * @param {Event} event A DOM2-normalized event object.
261 | * @return {void}
262 | */
263 | jqElem.on($.trim((opts.events + " ").split(" ").join("._idleTimer ")), function (e) {
264 | handleEvent(e);
265 | });
266 |
267 |
268 | // Internal Object Properties, This isn't all necessary, but we
269 | // explicitly define all keys here so we know what we are working with
270 | obj = $.extend({}, {
271 | olddate : +new Date(), // the last time state changed
272 | lastActive: +new Date(), // the last time timer was active
273 | idle : opts.idle, // current state
274 | idleBackup : opts.idle, // backup of idle parameter since it gets modified
275 | timeout : opts.timeout, // the interval to change state
276 | remaining : null, // how long until state changes
277 | tId : null, // the idle timer setTimeout
278 | pageX : null, // used to store the mouse coord
279 | pageY : null
280 | });
281 |
282 | // set a timeout to toggle state. May wish to omit this in some situations
283 | if (!obj.idle) {
284 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
285 | }
286 |
287 | // store our instance on the object
288 | $.data(elem, "idleTimerObj", obj);
289 |
290 | return jqElem;
291 | };
292 |
293 | // This allows binding to element
294 | $.fn.idleTimer = function (firstParam) {
295 | if (this[0]) {
296 | return $.idleTimer(firstParam, this[0]);
297 | }
298 |
299 | return this;
300 | };
301 |
302 | })(jQuery);
303 |
--------------------------------------------------------------------------------
/dist/idle-timer.1.0.0.min.js:
--------------------------------------------------------------------------------
1 | /*! Idle Timer v1.0.0 2014-03-10 | https://github.com/thorst/jquery-idletimer | (c) 2014 Paul Irish | Licensed MIT */
2 | !function(a){a.idleTimer=function(b,c){var d;"object"==typeof b?(d=b,b=null):"number"==typeof b&&(d={timeout:b},b=null),c=c||document,d=a.extend({idle:!1,timeout:3e4,events:"mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove"},d);var e=a(c),f=e.data("idleTimerObj")||{},g=function(b){var d=a.data(c,"idleTimerObj")||{};d.idle=!d.idle,d.olddate=+new Date;var e=a.Event((d.idle?"idle":"active")+".idleTimer");a(c).trigger(e,[c,a.extend({},d),b])},h=function(b){var d=a.data(c,"idleTimerObj")||{};if(null==d.remaining){if("mousemove"===b.type){if(b.pageX===d.pageX&&b.pageY===d.pageY)return;if("undefined"==typeof b.pageX&&"undefined"==typeof b.pageY)return;var e=+new Date-d.olddate;if(200>e)return}clearTimeout(d.tId),d.idle&&g(b),d.lastActive=+new Date,d.pageX=b.pageX,d.pageY=b.pageY,d.tId=setTimeout(g,d.timeout)}},i=function(){var b=a.data(c,"idleTimerObj")||{};b.idle=b.idleBackup,b.olddate=+new Date,b.lastActive=b.olddate,b.remaining=null,clearTimeout(b.tId),b.idle||(b.tId=setTimeout(g,b.timeout))},j=function(){var b=a.data(c,"idleTimerObj")||{};null==b.remaining&&(b.remaining=b.timeout-(+new Date-b.olddate),clearTimeout(b.tId))},k=function(){var b=a.data(c,"idleTimerObj")||{};null!=b.remaining&&(b.idle||(b.tId=setTimeout(g,b.remaining)),b.remaining=null)},l=function(){var b=a.data(c,"idleTimerObj")||{};clearTimeout(b.tId),e.removeData("idleTimerObj"),e.off("._idleTimer")},m=function(){var b=a.data(c,"idleTimerObj")||{};if(b.idle)return 0;if(null!=b.remaining)return b.remaining;var d=b.timeout-(+new Date-b.lastActive);return 0>d&&(d=0),d};if(null===b&&"undefined"!=typeof f.idle)return i(),e;if(null===b);else{if(null!==b&&"undefined"==typeof f.idle)return!1;if("destroy"===b)return l(),e;if("pause"===b)return j(),e;if("resume"===b)return k(),e;if("reset"===b)return i(),e;if("getRemainingTime"===b)return m();if("getElapsedTime"===b)return+new Date-f.olddate;if("getLastActiveTime"===b)return f.lastActive;if("isIdle"===b)return f.idle}return e.on(a.trim((d.events+" ").split(" ").join("._idleTimer ")),function(a){h(a)}),f=a.extend({},{olddate:+new Date,lastActive:+new Date,idle:d.idle,idleBackup:d.idle,timeout:d.timeout,remaining:null,tId:null,pageX:null,pageY:null}),f.idle||(f.tId=setTimeout(g,f.timeout)),a.data(c,"idleTimerObj",f),e},a.fn.idleTimer=function(b){return this[0]?a.idleTimer(b,this[0]):this}}(jQuery);
--------------------------------------------------------------------------------
/dist/idle-timer.1.0.1.js:
--------------------------------------------------------------------------------
1 | /*! Idle Timer - v1.0.1 - 2014-03-21
2 | * https://github.com/thorst/jquery-idletimer
3 | * Copyright (c) 2014 Paul Irish; Licensed MIT */
4 | /*
5 | mousewheel (deprecated) -> IE6.0, Chrome, Opera, Safari
6 | DOMMouseScroll (deprecated) -> Firefox 1.0
7 | wheel (standard) -> Chrome 31, Firefox 17, IE9, Firefox Mobile 17.0
8 |
9 | //No need to use, use DOMMouseScroll
10 | MozMousePixelScroll -> Firefox 3.5, Firefox Mobile 1.0
11 |
12 | //Events
13 | WheelEvent -> see wheel
14 | MouseWheelEvent -> see mousewheel
15 | MouseScrollEvent -> Firefox 3.5, Firefox Mobile 1.0
16 | */
17 | (function ($) {
18 |
19 | $.idleTimer = function (firstParam, elem) {
20 | var opts;
21 | if ( typeof firstParam === "object" ) {
22 | opts = firstParam;
23 | firstParam = null;
24 | } else if (typeof firstParam === "number") {
25 | opts = { timeout: firstParam };
26 | firstParam = null;
27 | }
28 |
29 | // element to watch
30 | elem = elem || document;
31 |
32 | // defaults that are to be stored as instance props on the elem
33 | opts = $.extend({
34 | idle: false, // indicates if the user is idle
35 | timeout: 30000, // the amount of time (ms) before the user is considered idle
36 | events: "mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove" // define active events
37 | }, opts);
38 |
39 | var jqElem = $(elem),
40 | obj = jqElem.data("idleTimerObj") || {},
41 |
42 | /* (intentionally not documented)
43 | * Toggles the idle state and fires an appropriate event.
44 | * @return {void}
45 | */
46 | toggleIdleState = function (e) {
47 |
48 | var obj = $.data(elem, "idleTimerObj") || {};
49 |
50 | // toggle the state
51 | obj.idle = !obj.idle;
52 |
53 | // store toggle state date time
54 | obj.olddate = +new Date();
55 |
56 | // create a custom event, with state and name space
57 | var event = $.Event((obj.idle ? "idle" : "active") + ".idleTimer");
58 |
59 | // trigger event on object with elem and copy of obj
60 | $(elem).trigger(event, [elem, $.extend({}, obj), e]);
61 | },
62 | /**
63 | * Handle event triggers
64 | * @return {void}
65 | * @method event
66 | * @static
67 | */
68 | handleEvent = function (e) {
69 |
70 | var obj = $.data(elem, "idleTimerObj") || {};
71 |
72 | // this is already paused, ignore events for now
73 | if (obj.remaining != null) { return; }
74 |
75 | /*
76 | mousemove is kinda buggy, it can be triggered when it should be idle.
77 | Typically is happening between 115 - 150 milliseconds after idle triggered.
78 | @psyafter & @kaellis report "always triggered if using modal (jQuery ui, with overlay)"
79 | @thorst has similar issues on ios7 "after $.scrollTop() on text area"
80 | */
81 | if (e.type === "mousemove") {
82 | // if coord are same, it didn't move
83 | if (e.pageX === obj.pageX && e.pageY === obj.pageY) {
84 | return;
85 | }
86 | // if coord don't exist how could it move
87 | if (typeof e.pageX === "undefined" && typeof e.pageY === "undefined") {
88 | return;
89 | }
90 | // under 200 ms is hard to do, and you would have to stop, as continuous activity will bypass this
91 | var elapsed = (+new Date()) - obj.olddate;
92 | if (elapsed < 200) {
93 | return;
94 | }
95 | }
96 |
97 | // clear any existing timeout
98 | clearTimeout(obj.tId);
99 |
100 | // if the idle timer is enabled, flip
101 | if (obj.idle) {
102 | toggleIdleState(e);
103 | }
104 |
105 | // store when user was last active
106 | obj.lastActive = +new Date();
107 |
108 | // update mouse coord
109 | obj.pageX = e.pageX;
110 | obj.pageY = e.pageY;
111 |
112 | // set a new timeout
113 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
114 |
115 | },
116 | /**
117 | * Restore initial settings and restart timer
118 | * @return {void}
119 | * @method reset
120 | * @static
121 | */
122 | reset = function () {
123 |
124 | var obj = $.data(elem, "idleTimerObj") || {};
125 |
126 | // reset settings
127 | obj.idle = obj.idleBackup;
128 | obj.olddate = +new Date();
129 | obj.lastActive = obj.olddate;
130 | obj.remaining = null;
131 |
132 | // reset Timers
133 | clearTimeout(obj.tId);
134 | if (!obj.idle) {
135 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
136 | }
137 |
138 | },
139 | /**
140 | * Store remaining time, stop timer
141 | * You can pause from an idle OR active state
142 | * @return {void}
143 | * @method pause
144 | * @static
145 | */
146 | pause = function () {
147 |
148 | var obj = $.data(elem, "idleTimerObj") || {};
149 |
150 | // this is already paused
151 | if ( obj.remaining != null ) { return; }
152 |
153 | // define how much is left on the timer
154 | obj.remaining = obj.timeout - ((+new Date()) - obj.olddate);
155 |
156 | // clear any existing timeout
157 | clearTimeout(obj.tId);
158 | },
159 | /**
160 | * Start timer with remaining value
161 | * @return {void}
162 | * @method resume
163 | * @static
164 | */
165 | resume = function () {
166 |
167 | var obj = $.data(elem, "idleTimerObj") || {};
168 |
169 | // this isn't paused yet
170 | if ( obj.remaining == null ) { return; }
171 |
172 | // start timer
173 | if ( !obj.idle ) {
174 | obj.tId = setTimeout(toggleIdleState, obj.remaining);
175 | }
176 |
177 | // clear remaining
178 | obj.remaining = null;
179 | },
180 | /**
181 | * Stops the idle timer. This removes appropriate event handlers
182 | * and cancels any pending timeouts.
183 | * @return {void}
184 | * @method destroy
185 | * @static
186 | */
187 | destroy = function () {
188 |
189 | var obj = $.data(elem, "idleTimerObj") || {};
190 |
191 | //clear any pending timeouts
192 | clearTimeout(obj.tId);
193 |
194 | //Remove data
195 | jqElem.removeData("idleTimerObj");
196 |
197 | //detach the event handlers
198 | jqElem.off("._idleTimer");
199 | },
200 | /**
201 | * Returns the time until becoming idle
202 | * @return {number}
203 | * @method remainingtime
204 | * @static
205 | */
206 | remainingtime = function () {
207 |
208 | var obj = $.data(elem, "idleTimerObj") || {};
209 |
210 | //If idle there is no time remaining
211 | if ( obj.idle ) { return 0; }
212 |
213 | //If its paused just return that
214 | if ( obj.remaining != null ) { return obj.remaining; }
215 |
216 | //Determine remaining, if negative idle didn't finish flipping, just return 0
217 | var remaining = obj.timeout - ((+new Date()) - obj.lastActive);
218 | if (remaining < 0) { remaining = 0; }
219 |
220 | //If this is paused return that number, else return current remaining
221 | return remaining;
222 | };
223 |
224 |
225 | // determine which function to call
226 | if (firstParam === null && typeof obj.idle !== "undefined") {
227 | // they think they want to init, but it already is, just reset
228 | reset();
229 | return jqElem;
230 | } else if (firstParam === null) {
231 | // they want to init
232 | } else if (firstParam !== null && typeof obj.idle === "undefined") {
233 | // they want to do something, but it isnt init
234 | // not sure the best way to handle this
235 | return false;
236 | } else if (firstParam === "destroy") {
237 | destroy();
238 | return jqElem;
239 | } else if (firstParam === "pause") {
240 | pause();
241 | return jqElem;
242 | } else if (firstParam === "resume") {
243 | resume();
244 | return jqElem;
245 | } else if (firstParam === "reset") {
246 | reset();
247 | return jqElem;
248 | } else if (firstParam === "getRemainingTime") {
249 | return remainingtime();
250 | } else if (firstParam === "getElapsedTime") {
251 | return (+new Date()) - obj.olddate;
252 | } else if (firstParam === "getLastActiveTime") {
253 | return obj.lastActive;
254 | } else if (firstParam === "isIdle") {
255 | return obj.idle;
256 | }
257 |
258 | /* (intentionally not documented)
259 | * Handles a user event indicating that the user isn't idle. namespaced with internal idleTimer
260 | * @param {Event} event A DOM2-normalized event object.
261 | * @return {void}
262 | */
263 | jqElem.on($.trim((opts.events + " ").split(" ").join("._idleTimer ")), function (e) {
264 | handleEvent(e);
265 | });
266 |
267 |
268 | // Internal Object Properties, This isn't all necessary, but we
269 | // explicitly define all keys here so we know what we are working with
270 | obj = $.extend({}, {
271 | olddate : +new Date(), // the last time state changed
272 | lastActive: +new Date(), // the last time timer was active
273 | idle : opts.idle, // current state
274 | idleBackup : opts.idle, // backup of idle parameter since it gets modified
275 | timeout : opts.timeout, // the interval to change state
276 | remaining : null, // how long until state changes
277 | tId : null, // the idle timer setTimeout
278 | pageX : null, // used to store the mouse coord
279 | pageY : null
280 | });
281 |
282 | // set a timeout to toggle state. May wish to omit this in some situations
283 | if (!obj.idle) {
284 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
285 | }
286 |
287 | // store our instance on the object
288 | $.data(elem, "idleTimerObj", obj);
289 |
290 | return jqElem;
291 | };
292 |
293 | // This allows binding to element
294 | $.fn.idleTimer = function (firstParam) {
295 | if (this[0]) {
296 | return $.idleTimer(firstParam, this[0]);
297 | }
298 |
299 | return this;
300 | };
301 |
302 | })(jQuery);
303 |
--------------------------------------------------------------------------------
/dist/idle-timer.1.0.1.min.js:
--------------------------------------------------------------------------------
1 | /*! Idle Timer v1.0.1 2014-03-21 | https://github.com/thorst/jquery-idletimer | (c) 2014 Paul Irish | Licensed MIT */
2 | !function(a){a.idleTimer=function(b,c){var d;"object"==typeof b?(d=b,b=null):"number"==typeof b&&(d={timeout:b},b=null),c=c||document,d=a.extend({idle:!1,timeout:3e4,events:"mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove"},d);var e=a(c),f=e.data("idleTimerObj")||{},g=function(b){var d=a.data(c,"idleTimerObj")||{};d.idle=!d.idle,d.olddate=+new Date;var e=a.Event((d.idle?"idle":"active")+".idleTimer");a(c).trigger(e,[c,a.extend({},d),b])},h=function(b){var d=a.data(c,"idleTimerObj")||{};if(null==d.remaining){if("mousemove"===b.type){if(b.pageX===d.pageX&&b.pageY===d.pageY)return;if("undefined"==typeof b.pageX&&"undefined"==typeof b.pageY)return;var e=+new Date-d.olddate;if(200>e)return}clearTimeout(d.tId),d.idle&&g(b),d.lastActive=+new Date,d.pageX=b.pageX,d.pageY=b.pageY,d.tId=setTimeout(g,d.timeout)}},i=function(){var b=a.data(c,"idleTimerObj")||{};b.idle=b.idleBackup,b.olddate=+new Date,b.lastActive=b.olddate,b.remaining=null,clearTimeout(b.tId),b.idle||(b.tId=setTimeout(g,b.timeout))},j=function(){var b=a.data(c,"idleTimerObj")||{};null==b.remaining&&(b.remaining=b.timeout-(+new Date-b.olddate),clearTimeout(b.tId))},k=function(){var b=a.data(c,"idleTimerObj")||{};null!=b.remaining&&(b.idle||(b.tId=setTimeout(g,b.remaining)),b.remaining=null)},l=function(){var b=a.data(c,"idleTimerObj")||{};clearTimeout(b.tId),e.removeData("idleTimerObj"),e.off("._idleTimer")},m=function(){var b=a.data(c,"idleTimerObj")||{};if(b.idle)return 0;if(null!=b.remaining)return b.remaining;var d=b.timeout-(+new Date-b.lastActive);return 0>d&&(d=0),d};if(null===b&&"undefined"!=typeof f.idle)return i(),e;if(null===b);else{if(null!==b&&"undefined"==typeof f.idle)return!1;if("destroy"===b)return l(),e;if("pause"===b)return j(),e;if("resume"===b)return k(),e;if("reset"===b)return i(),e;if("getRemainingTime"===b)return m();if("getElapsedTime"===b)return+new Date-f.olddate;if("getLastActiveTime"===b)return f.lastActive;if("isIdle"===b)return f.idle}return e.on(a.trim((d.events+" ").split(" ").join("._idleTimer ")),function(a){h(a)}),f=a.extend({},{olddate:+new Date,lastActive:+new Date,idle:d.idle,idleBackup:d.idle,timeout:d.timeout,remaining:null,tId:null,pageX:null,pageY:null}),f.idle||(f.tId=setTimeout(g,f.timeout)),a.data(c,"idleTimerObj",f),e},a.fn.idleTimer=function(b){return this[0]?a.idleTimer(b,this[0]):this}}(jQuery);
--------------------------------------------------------------------------------
/dist/idle-timer.1.1.0.js:
--------------------------------------------------------------------------------
1 | /*! Idle Timer - v1.1.0 - 2016-03-21
2 | * https://github.com/thorst/jquery-idletimer
3 | * Copyright (c) 2016 Paul Irish; Licensed MIT */
4 | /*
5 | mousewheel (deprecated) -> IE6.0, Chrome, Opera, Safari
6 | DOMMouseScroll (deprecated) -> Firefox 1.0
7 | wheel (standard) -> Chrome 31, Firefox 17, IE9, Firefox Mobile 17.0
8 |
9 | //No need to use, use DOMMouseScroll
10 | MozMousePixelScroll -> Firefox 3.5, Firefox Mobile 1.0
11 |
12 | //Events
13 | WheelEvent -> see wheel
14 | MouseWheelEvent -> see mousewheel
15 | MouseScrollEvent -> Firefox 3.5, Firefox Mobile 1.0
16 | */
17 | (function ($) {
18 |
19 | $.idleTimer = function (firstParam, elem) {
20 | var opts;
21 | if ( typeof firstParam === "object" ) {
22 | opts = firstParam;
23 | firstParam = null;
24 | } else if (typeof firstParam === "number") {
25 | opts = { timeout: firstParam };
26 | firstParam = null;
27 | }
28 |
29 | // element to watch
30 | elem = elem || document;
31 |
32 | // defaults that are to be stored as instance props on the elem
33 | opts = $.extend({
34 | idle: false, // indicates if the user is idle
35 | timeout: 30000, // the amount of time (ms) before the user is considered idle
36 | events: "mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove" // define active events
37 | }, opts);
38 |
39 | var jqElem = $(elem),
40 | obj = jqElem.data("idleTimerObj") || {},
41 |
42 | /* (intentionally not documented)
43 | * Toggles the idle state and fires an appropriate event.
44 | * @return {void}
45 | */
46 | toggleIdleState = function (e) {
47 | var obj = $.data(elem, "idleTimerObj") || {};
48 |
49 | // toggle the state
50 | obj.idle = !obj.idle;
51 |
52 | // store toggle state date time
53 | obj.olddate = +new Date();
54 |
55 | // create a custom event, with state and name space
56 | var event = $.Event((obj.idle ? "idle" : "active") + ".idleTimer");
57 |
58 | // trigger event on object with elem and copy of obj
59 | $(elem).trigger(event, [elem, $.extend({}, obj), e]);
60 | },
61 | /**
62 | * Handle event triggers
63 | * @return {void}
64 | * @method event
65 | * @static
66 | */
67 | handleEvent = function (e) {
68 | var obj = $.data(elem, "idleTimerObj") || {};
69 |
70 | if (e.type === "storage" && e.originalEvent.key !== obj.timerSyncId) {
71 | return;
72 | }
73 |
74 | // this is already paused, ignore events for now
75 | if (obj.remaining != null) { return; }
76 |
77 | /*
78 | mousemove is kinda buggy, it can be triggered when it should be idle.
79 | Typically is happening between 115 - 150 milliseconds after idle triggered.
80 | @psyafter & @kaellis report "always triggered if using modal (jQuery ui, with overlay)"
81 | @thorst has similar issues on ios7 "after $.scrollTop() on text area"
82 | */
83 | if (e.type === "mousemove") {
84 | // if coord are same, it didn't move
85 | if (e.pageX === obj.pageX && e.pageY === obj.pageY) {
86 | return;
87 | }
88 | // if coord don't exist how could it move
89 | if (typeof e.pageX === "undefined" && typeof e.pageY === "undefined") {
90 | return;
91 | }
92 | // under 200 ms is hard to do, and you would have to stop, as continuous activity will bypass this
93 | var elapsed = (+new Date()) - obj.olddate;
94 | if (elapsed < 200) {
95 | return;
96 | }
97 | }
98 |
99 | // clear any existing timeout
100 | clearTimeout(obj.tId);
101 |
102 | // if the idle timer is enabled, flip
103 | if (obj.idle) {
104 | toggleIdleState(e);
105 | }
106 |
107 | // store when user was last active
108 | obj.lastActive = +new Date();
109 |
110 | // update mouse coord
111 | obj.pageX = e.pageX;
112 | obj.pageY = e.pageY;
113 |
114 | // sync lastActive
115 | if (e.type !== "storage" && obj.timerSyncId) {
116 | if (typeof(localStorage) !== "undefined") {
117 | localStorage.setItem(obj.timerSyncId, obj.lastActive);
118 | }
119 | }
120 |
121 | // set a new timeout
122 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
123 | },
124 | /**
125 | * Restore initial settings and restart timer
126 | * @return {void}
127 | * @method reset
128 | * @static
129 | */
130 | reset = function () {
131 |
132 | var obj = $.data(elem, "idleTimerObj") || {};
133 |
134 | // reset settings
135 | obj.idle = obj.idleBackup;
136 | obj.olddate = +new Date();
137 | obj.lastActive = obj.olddate;
138 | obj.remaining = null;
139 |
140 | // reset Timers
141 | clearTimeout(obj.tId);
142 | if (!obj.idle) {
143 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
144 | }
145 |
146 | },
147 | /**
148 | * Store remaining time, stop timer
149 | * You can pause from an idle OR active state
150 | * @return {void}
151 | * @method pause
152 | * @static
153 | */
154 | pause = function () {
155 |
156 | var obj = $.data(elem, "idleTimerObj") || {};
157 |
158 | // this is already paused
159 | if ( obj.remaining != null ) { return; }
160 |
161 | // define how much is left on the timer
162 | obj.remaining = obj.timeout - ((+new Date()) - obj.olddate);
163 |
164 | // clear any existing timeout
165 | clearTimeout(obj.tId);
166 | },
167 | /**
168 | * Start timer with remaining value
169 | * @return {void}
170 | * @method resume
171 | * @static
172 | */
173 | resume = function () {
174 |
175 | var obj = $.data(elem, "idleTimerObj") || {};
176 |
177 | // this isn't paused yet
178 | if ( obj.remaining == null ) { return; }
179 |
180 | // start timer
181 | if ( !obj.idle ) {
182 | obj.tId = setTimeout(toggleIdleState, obj.remaining);
183 | }
184 |
185 | // clear remaining
186 | obj.remaining = null;
187 | },
188 | /**
189 | * Stops the idle timer. This removes appropriate event handlers
190 | * and cancels any pending timeouts.
191 | * @return {void}
192 | * @method destroy
193 | * @static
194 | */
195 | destroy = function () {
196 |
197 | var obj = $.data(elem, "idleTimerObj") || {};
198 |
199 | //clear any pending timeouts
200 | clearTimeout(obj.tId);
201 |
202 | //Remove data
203 | jqElem.removeData("idleTimerObj");
204 |
205 | //detach the event handlers
206 | jqElem.off("._idleTimer");
207 | },
208 | /**
209 | * Returns the time until becoming idle
210 | * @return {number}
211 | * @method remainingtime
212 | * @static
213 | */
214 | remainingtime = function () {
215 |
216 | var obj = $.data(elem, "idleTimerObj") || {};
217 |
218 | //If idle there is no time remaining
219 | if ( obj.idle ) { return 0; }
220 |
221 | //If its paused just return that
222 | if ( obj.remaining != null ) { return obj.remaining; }
223 |
224 | //Determine remaining, if negative idle didn't finish flipping, just return 0
225 | var remaining = obj.timeout - ((+new Date()) - obj.lastActive);
226 | if (remaining < 0) { remaining = 0; }
227 |
228 | //If this is paused return that number, else return current remaining
229 | return remaining;
230 | };
231 |
232 |
233 | // determine which function to call
234 | if (firstParam === null && typeof obj.idle !== "undefined") {
235 | // they think they want to init, but it already is, just reset
236 | reset();
237 | return jqElem;
238 | } else if (firstParam === null) {
239 | // they want to init
240 | } else if (firstParam !== null && typeof obj.idle === "undefined") {
241 | // they want to do something, but it isnt init
242 | // not sure the best way to handle this
243 | return false;
244 | } else if (firstParam === "destroy") {
245 | destroy();
246 | return jqElem;
247 | } else if (firstParam === "pause") {
248 | pause();
249 | return jqElem;
250 | } else if (firstParam === "resume") {
251 | resume();
252 | return jqElem;
253 | } else if (firstParam === "reset") {
254 | reset();
255 | return jqElem;
256 | } else if (firstParam === "getRemainingTime") {
257 | return remainingtime();
258 | } else if (firstParam === "getElapsedTime") {
259 | return (+new Date()) - obj.olddate;
260 | } else if (firstParam === "getLastActiveTime") {
261 | return obj.lastActive;
262 | } else if (firstParam === "isIdle") {
263 | return obj.idle;
264 | }
265 |
266 | /* (intentionally not documented)
267 | * Handles a user event indicating that the user isn't idle. namespaced with internal idleTimer
268 | * @param {Event} event A DOM2-normalized event object.
269 | * @return {void}
270 | */
271 | jqElem.on($.trim((opts.events + " ").split(" ").join("._idleTimer ")), function (e) {
272 | handleEvent(e);
273 | });
274 |
275 | if (opts.timerSyncId) {
276 | $(window).bind("storage", handleEvent);
277 | }
278 |
279 | // Internal Object Properties, This isn't all necessary, but we
280 | // explicitly define all keys here so we know what we are working with
281 | obj = $.extend({}, {
282 | olddate : +new Date(), // the last time state changed
283 | lastActive: +new Date(), // the last time timer was active
284 | idle : opts.idle, // current state
285 | idleBackup : opts.idle, // backup of idle parameter since it gets modified
286 | timeout : opts.timeout, // the interval to change state
287 | remaining : null, // how long until state changes
288 | timerSyncId : opts.timerSyncId, // localStorage key to use for syncing this timer
289 | tId : null, // the idle timer setTimeout
290 | pageX : null, // used to store the mouse coord
291 | pageY : null
292 | });
293 |
294 | // set a timeout to toggle state. May wish to omit this in some situations
295 | if (!obj.idle) {
296 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
297 | }
298 |
299 | // store our instance on the object
300 | $.data(elem, "idleTimerObj", obj);
301 |
302 | return jqElem;
303 | };
304 |
305 | // This allows binding to element
306 | $.fn.idleTimer = function (firstParam) {
307 | if (this[0]) {
308 | return $.idleTimer(firstParam, this[0]);
309 | }
310 |
311 | return this;
312 | };
313 |
314 | })(jQuery);
315 |
--------------------------------------------------------------------------------
/dist/idle-timer.1.1.0.min.js:
--------------------------------------------------------------------------------
1 | /*! Idle Timer v1.1.0 2016-03-21 | https://github.com/thorst/jquery-idletimer | (c) 2016 Paul Irish | Licensed MIT */
2 | !function(a){a.idleTimer=function(b,c){var d;"object"==typeof b?(d=b,b=null):"number"==typeof b&&(d={timeout:b},b=null),c=c||document,d=a.extend({idle:!1,timeout:3e4,events:"mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove"},d);var e=a(c),f=e.data("idleTimerObj")||{},g=function(b){var d=a.data(c,"idleTimerObj")||{};d.idle=!d.idle,d.olddate=+new Date;var e=a.Event((d.idle?"idle":"active")+".idleTimer");a(c).trigger(e,[c,a.extend({},d),b])},h=function(b){var d=a.data(c,"idleTimerObj")||{};if(("storage"!==b.type||b.originalEvent.key===d.timerSyncId)&&null==d.remaining){if("mousemove"===b.type){if(b.pageX===d.pageX&&b.pageY===d.pageY)return;if("undefined"==typeof b.pageX&&"undefined"==typeof b.pageY)return;var e=+new Date-d.olddate;if(200>e)return}clearTimeout(d.tId),d.idle&&g(b),d.lastActive=+new Date,d.pageX=b.pageX,d.pageY=b.pageY,"storage"!==b.type&&d.timerSyncId&&"undefined"!=typeof localStorage&&localStorage.setItem(d.timerSyncId,d.lastActive),d.tId=setTimeout(g,d.timeout)}},i=function(){var b=a.data(c,"idleTimerObj")||{};b.idle=b.idleBackup,b.olddate=+new Date,b.lastActive=b.olddate,b.remaining=null,clearTimeout(b.tId),b.idle||(b.tId=setTimeout(g,b.timeout))},j=function(){var b=a.data(c,"idleTimerObj")||{};null==b.remaining&&(b.remaining=b.timeout-(+new Date-b.olddate),clearTimeout(b.tId))},k=function(){var b=a.data(c,"idleTimerObj")||{};null!=b.remaining&&(b.idle||(b.tId=setTimeout(g,b.remaining)),b.remaining=null)},l=function(){var b=a.data(c,"idleTimerObj")||{};clearTimeout(b.tId),e.removeData("idleTimerObj"),e.off("._idleTimer")},m=function(){var b=a.data(c,"idleTimerObj")||{};if(b.idle)return 0;if(null!=b.remaining)return b.remaining;var d=b.timeout-(+new Date-b.lastActive);return 0>d&&(d=0),d};if(null===b&&"undefined"!=typeof f.idle)return i(),e;if(null===b);else{if(null!==b&&"undefined"==typeof f.idle)return!1;if("destroy"===b)return l(),e;if("pause"===b)return j(),e;if("resume"===b)return k(),e;if("reset"===b)return i(),e;if("getRemainingTime"===b)return m();if("getElapsedTime"===b)return+new Date-f.olddate;if("getLastActiveTime"===b)return f.lastActive;if("isIdle"===b)return f.idle}return e.on(a.trim((d.events+" ").split(" ").join("._idleTimer ")),function(a){h(a)}),d.timerSyncId&&a(window).bind("storage",h),f=a.extend({},{olddate:+new Date,lastActive:+new Date,idle:d.idle,idleBackup:d.idle,timeout:d.timeout,remaining:null,timerSyncId:d.timerSyncId,tId:null,pageX:null,pageY:null}),f.idle||(f.tId=setTimeout(g,f.timeout)),a.data(c,"idleTimerObj",f),e},a.fn.idleTimer=function(b){return this[0]?a.idleTimer(b,this[0]):this}}(jQuery);
--------------------------------------------------------------------------------
/dist/idle-timer.1.1.1.js:
--------------------------------------------------------------------------------
1 | /*! Idle Timer - v1.1.1 - 2020-06-25
2 | * https://github.com/thorst/jquery-idletimer
3 | * Copyright (c) 2020 Paul Irish; Licensed MIT */
4 | /*
5 | mousewheel (deprecated) -> IE6.0, Chrome, Opera, Safari
6 | DOMMouseScroll (deprecated) -> Firefox 1.0
7 | wheel (standard) -> Chrome 31, Firefox 17, IE9, Firefox Mobile 17.0
8 |
9 | //No need to use, use DOMMouseScroll
10 | MozMousePixelScroll -> Firefox 3.5, Firefox Mobile 1.0
11 |
12 | //Events
13 | WheelEvent -> see wheel
14 | MouseWheelEvent -> see mousewheel
15 | MouseScrollEvent -> Firefox 3.5, Firefox Mobile 1.0
16 | */
17 | (function ($) {
18 |
19 | $.idleTimer = function (firstParam, elem) {
20 | var opts;
21 | if ( typeof firstParam === "object" ) {
22 | opts = firstParam;
23 | firstParam = null;
24 | } else if (typeof firstParam === "number") {
25 | opts = { timeout: firstParam };
26 | firstParam = null;
27 | }
28 |
29 | // element to watch
30 | elem = elem || document;
31 |
32 | // defaults that are to be stored as instance props on the elem
33 | opts = $.extend({
34 | idle: false, // indicates if the user is idle
35 | timeout: 30000, // the amount of time (ms) before the user is considered idle
36 | events: "mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove" // define active events
37 | }, opts);
38 |
39 | var jqElem = $(elem),
40 | obj = jqElem.data("idleTimerObj") || {},
41 |
42 | /* (intentionally not documented)
43 | * Toggles the idle state and fires an appropriate event.
44 | * @return {void}
45 | */
46 | toggleIdleState = function (e) {
47 | var obj = $.data(elem, "idleTimerObj") || {};
48 |
49 | // toggle the state
50 | obj.idle = !obj.idle;
51 |
52 | // store toggle state date time
53 | obj.olddate = +new Date();
54 |
55 | // create a custom event, with state and name space
56 | var event = $.Event((obj.idle ? "idle" : "active") + ".idleTimer");
57 |
58 | // trigger event on object with elem and copy of obj
59 | $(elem).trigger(event, [elem, $.extend({}, obj), e]);
60 | },
61 | /**
62 | * Handle event triggers
63 | * @return {void}
64 | * @method event
65 | * @static
66 | */
67 | handleEvent = function (e) {
68 | var obj = $.data(elem, "idleTimerObj") || {};
69 |
70 | // ignore writting to storage unless related to idleTimer
71 | if (e.type === "storage" && e.originalEvent.key !== obj.timerSyncId) {
72 | return;
73 | }
74 |
75 | // this is already paused, ignore events for now
76 | if (obj.remaining != null) { return; }
77 |
78 | /*
79 | mousemove is kinda buggy, it can be triggered when it should be idle.
80 | Typically is happening between 115 - 150 milliseconds after idle triggered.
81 | @psyafter & @kaellis report "always triggered if using modal (jQuery ui, with overlay)"
82 | @thorst has similar issues on ios7 "after $.scrollTop() on text area"
83 | */
84 | if (e.type === "mousemove") {
85 | // if coord are same, it didn't move
86 | if (e.pageX === obj.pageX && e.pageY === obj.pageY) {
87 | return;
88 | }
89 | // if coord don't exist how could it move
90 | if (typeof e.pageX === "undefined" && typeof e.pageY === "undefined") {
91 | return;
92 | }
93 | // under 200 ms is hard to do, and you would have to stop, as continuous activity will bypass this
94 | var elapsed = (+new Date()) - obj.olddate;
95 | if (elapsed < 200) {
96 | return;
97 | }
98 | }
99 |
100 | // clear any existing timeout
101 | clearTimeout(obj.tId);
102 |
103 | // if the idle timer is enabled, flip
104 | if (obj.idle) {
105 | toggleIdleState(e);
106 | }
107 |
108 | // store when user was last active
109 | obj.lastActive = +new Date();
110 |
111 | // update mouse coord
112 | obj.pageX = e.pageX;
113 | obj.pageY = e.pageY;
114 |
115 | // sync lastActive
116 | if (e.type !== "storage" && obj.timerSyncId) {
117 | if (typeof(localStorage) !== "undefined") {
118 | localStorage.setItem(obj.timerSyncId, obj.lastActive);
119 | }
120 | }
121 |
122 | // set a new timeout
123 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
124 | },
125 | /**
126 | * Restore initial settings and restart timer
127 | * @return {void}
128 | * @method reset
129 | * @static
130 | */
131 | reset = function () {
132 |
133 | var obj = $.data(elem, "idleTimerObj") || {};
134 |
135 | // reset settings
136 | obj.idle = obj.idleBackup;
137 | obj.olddate = +new Date();
138 | obj.lastActive = obj.olddate;
139 | obj.remaining = null;
140 |
141 | // reset Timers
142 | clearTimeout(obj.tId);
143 | if (!obj.idle) {
144 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
145 | }
146 |
147 | },
148 | /**
149 | * Store remaining time, stop timer
150 | * You can pause from an idle OR active state
151 | * @return {void}
152 | * @method pause
153 | * @static
154 | */
155 | pause = function () {
156 |
157 | var obj = $.data(elem, "idleTimerObj") || {};
158 |
159 | // this is already paused
160 | if ( obj.remaining != null ) { return; }
161 |
162 | // define how much is left on the timer
163 | obj.remaining = obj.timeout - ((+new Date()) - obj.olddate);
164 |
165 | // clear any existing timeout
166 | clearTimeout(obj.tId);
167 | },
168 | /**
169 | * Start timer with remaining value
170 | * @return {void}
171 | * @method resume
172 | * @static
173 | */
174 | resume = function () {
175 |
176 | var obj = $.data(elem, "idleTimerObj") || {};
177 |
178 | // this isn't paused yet
179 | if ( obj.remaining == null ) { return; }
180 |
181 | // start timer
182 | if ( !obj.idle ) {
183 | obj.tId = setTimeout(toggleIdleState, obj.remaining);
184 | }
185 |
186 | // clear remaining
187 | obj.remaining = null;
188 | },
189 | /**
190 | * Stops the idle timer. This removes appropriate event handlers
191 | * and cancels any pending timeouts.
192 | * @return {void}
193 | * @method destroy
194 | * @static
195 | */
196 | destroy = function () {
197 |
198 | var obj = $.data(elem, "idleTimerObj") || {};
199 |
200 | //clear any pending timeouts
201 | clearTimeout(obj.tId);
202 |
203 | //Remove data
204 | jqElem.removeData("idleTimerObj");
205 |
206 | //detach the event handlers
207 | jqElem.off("._idleTimer");
208 | },
209 | /**
210 | * Returns the time until becoming idle
211 | * @return {number}
212 | * @method remainingtime
213 | * @static
214 | */
215 | remainingtime = function () {
216 |
217 | var obj = $.data(elem, "idleTimerObj") || {};
218 |
219 | //If idle there is no time remaining
220 | if ( obj.idle ) { return 0; }
221 |
222 | //If its paused just return that
223 | if ( obj.remaining != null ) { return obj.remaining; }
224 |
225 | //Determine remaining, if negative idle didn't finish flipping, just return 0
226 | var remaining = obj.timeout - ((+new Date()) - obj.lastActive);
227 | if (remaining < 0) { remaining = 0; }
228 |
229 | //If this is paused return that number, else return current remaining
230 | return remaining;
231 | };
232 |
233 |
234 | // determine which function to call
235 | if (firstParam === null && typeof obj.idle !== "undefined") {
236 | // they think they want to init, but it already is, just reset
237 | reset();
238 | return jqElem;
239 | } else if (firstParam === null) {
240 | // they want to init
241 | } else if (firstParam !== null && typeof obj.idle === "undefined") {
242 | // they want to do something, but it isnt init
243 | // not sure the best way to handle this
244 | return false;
245 | } else if (firstParam === "destroy") {
246 | destroy();
247 | return jqElem;
248 | } else if (firstParam === "pause") {
249 | pause();
250 | return jqElem;
251 | } else if (firstParam === "resume") {
252 | resume();
253 | return jqElem;
254 | } else if (firstParam === "reset") {
255 | reset();
256 | return jqElem;
257 | } else if (firstParam === "getRemainingTime") {
258 | return remainingtime();
259 | } else if (firstParam === "getElapsedTime") {
260 | return (+new Date()) - obj.olddate;
261 | } else if (firstParam === "getLastActiveTime") {
262 | return obj.lastActive;
263 | } else if (firstParam === "isIdle") {
264 | return obj.idle;
265 | }
266 |
267 | // Test via a getter in the options object to see if the passive property is accessed
268 | // This isnt working in jquery, though is planned for 4.0
269 | // https://github.com/jquery/jquery/issues/2871
270 | /*var supportsPassive = false;
271 | try {
272 | var Popts = Object.defineProperty({}, "passive", {
273 | get: function() {
274 | supportsPassive = true;
275 | }
276 | });
277 | window.addEventListener("test", null, Popts);
278 | } catch (e) {}
279 | */
280 |
281 | /* (intentionally not documented)
282 | * Handles a user event indicating that the user isn't idle. namespaced with internal idleTimer
283 | * @param {Event} event A DOM2-normalized event object.
284 | * @return {void}
285 | */
286 | jqElem.on((opts.events + " ").split(" ").join("._idleTimer ").trim(), function (e) {
287 | handleEvent(e);
288 | });
289 | //}, supportsPassive ? { passive: true } : false);
290 |
291 | if (opts.timerSyncId) {
292 | $(window).on("storage", handleEvent);
293 | }
294 |
295 | // Internal Object Properties, This isn't all necessary, but we
296 | // explicitly define all keys here so we know what we are working with
297 | obj = $.extend({}, {
298 | olddate : +new Date(), // the last time state changed
299 | lastActive: +new Date(), // the last time timer was active
300 | idle : opts.idle, // current state
301 | idleBackup : opts.idle, // backup of idle parameter since it gets modified
302 | timeout : opts.timeout, // the interval to change state
303 | remaining : null, // how long until state changes
304 | timerSyncId : opts.timerSyncId, // localStorage key to use for syncing this timer
305 | tId : null, // the idle timer setTimeout
306 | pageX : null, // used to store the mouse coord
307 | pageY : null
308 | });
309 |
310 | // set a timeout to toggle state. May wish to omit this in some situations
311 | if (!obj.idle) {
312 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
313 | }
314 |
315 | // store our instance on the object
316 | $.data(elem, "idleTimerObj", obj);
317 |
318 | return jqElem;
319 | };
320 |
321 | // This allows binding to element
322 | $.fn.idleTimer = function (firstParam) {
323 | if (this[0]) {
324 | return $.idleTimer(firstParam, this[0]);
325 | }
326 |
327 | return this;
328 | };
329 |
330 | })(jQuery);
331 |
--------------------------------------------------------------------------------
/dist/idle-timer.1.1.1.min.js:
--------------------------------------------------------------------------------
1 | /*! Idle Timer v1.1.1 2020-06-25 | https://github.com/thorst/jquery-idletimer | (c) 2020 Paul Irish | Licensed MIT */
2 |
3 | !function(c){c.idleTimer=function(e,n){var i;"object"==typeof e?(i=e,e=null):"number"==typeof e&&(i={timeout:e},e=null),n=n||document,i=c.extend({idle:!1,timeout:3e4,events:"mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove"},i);function t(e){var i=c.data(n,"idleTimerObj")||{};i.idle=!i.idle,i.olddate=+new Date;var t=c.Event((i.idle?"idle":"active")+".idleTimer");c(n).trigger(t,[n,c.extend({},i),e])}function r(e){var i=c.data(n,"idleTimerObj")||{};if(("storage"!==e.type||e.originalEvent.key===i.timerSyncId)&&null==i.remaining){if("mousemove"===e.type){if(e.pageX===i.pageX&&e.pageY===i.pageY)return;if(void 0===e.pageX&&void 0===e.pageY)return;if(new Date-i.olddate<200)return}clearTimeout(i.tId),i.idle&&t(e),i.lastActive=+new Date,i.pageX=e.pageX,i.pageY=e.pageY,"storage"!==e.type&&i.timerSyncId&&"undefined"!=typeof localStorage&&localStorage.setItem(i.timerSyncId,i.lastActive),i.tId=setTimeout(t,i.timeout)}}function l(){var e=c.data(n,"idleTimerObj")||{};e.idle=e.idleBackup,e.olddate=+new Date,e.lastActive=e.olddate,e.remaining=null,clearTimeout(e.tId),e.idle||(e.tId=setTimeout(t,e.timeout))}var a,d,o,u=c(n),m=u.data("idleTimerObj")||{};if(null===e&&void 0!==m.idle)return l(),u;if(null!==e){if(null!==e&&void 0===m.idle)return!1;if("destroy"===e)return o=c.data(n,"idleTimerObj")||{},clearTimeout(o.tId),u.removeData("idleTimerObj"),u.off("._idleTimer"),u;if("pause"===e)return null==(d=c.data(n,"idleTimerObj")||{}).remaining&&(d.remaining=d.timeout-(new Date-d.olddate),clearTimeout(d.tId)),u;if("resume"===e)return null!=(a=c.data(n,"idleTimerObj")||{}).remaining&&(a.idle||(a.tId=setTimeout(t,a.remaining)),a.remaining=null),u;if("reset"===e)return l(),u;if("getRemainingTime"===e)return function(){var e=c.data(n,"idleTimerObj")||{};if(e.idle)return 0;if(null!=e.remaining)return e.remaining;var i=e.timeout-(new Date-e.lastActive);return i<0&&(i=0),i}();if("getElapsedTime"===e)return new Date-m.olddate;if("getLastActiveTime"===e)return m.lastActive;if("isIdle"===e)return m.idle}return u.on((i.events+" ").split(" ").join("._idleTimer ").trim(),function(e){r(e)}),i.timerSyncId&&c(window).on("storage",r),(m=c.extend({},{olddate:+new Date,lastActive:+new Date,idle:i.idle,idleBackup:i.idle,timeout:i.timeout,remaining:null,timerSyncId:i.timerSyncId,tId:null,pageX:null,pageY:null})).idle||(m.tId=setTimeout(t,m.timeout)),c.data(n,"idleTimerObj",m),u},c.fn.idleTimer=function(e){return this[0]?c.idleTimer(e,this[0]):this}}(jQuery);
--------------------------------------------------------------------------------
/dist/idle-timer.js:
--------------------------------------------------------------------------------
1 | /*! Idle Timer - v1.1.1 - 2020-06-25
2 | * https://github.com/thorst/jquery-idletimer
3 | * Copyright (c) 2020 Paul Irish; Licensed MIT */
4 | /*
5 | mousewheel (deprecated) -> IE6.0, Chrome, Opera, Safari
6 | DOMMouseScroll (deprecated) -> Firefox 1.0
7 | wheel (standard) -> Chrome 31, Firefox 17, IE9, Firefox Mobile 17.0
8 |
9 | //No need to use, use DOMMouseScroll
10 | MozMousePixelScroll -> Firefox 3.5, Firefox Mobile 1.0
11 |
12 | //Events
13 | WheelEvent -> see wheel
14 | MouseWheelEvent -> see mousewheel
15 | MouseScrollEvent -> Firefox 3.5, Firefox Mobile 1.0
16 | */
17 | (function ($) {
18 |
19 | $.idleTimer = function (firstParam, elem) {
20 | var opts;
21 | if ( typeof firstParam === "object" ) {
22 | opts = firstParam;
23 | firstParam = null;
24 | } else if (typeof firstParam === "number") {
25 | opts = { timeout: firstParam };
26 | firstParam = null;
27 | }
28 |
29 | // element to watch
30 | elem = elem || document;
31 |
32 | // defaults that are to be stored as instance props on the elem
33 | opts = $.extend({
34 | idle: false, // indicates if the user is idle
35 | timeout: 30000, // the amount of time (ms) before the user is considered idle
36 | events: "mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove" // define active events
37 | }, opts);
38 |
39 | var jqElem = $(elem),
40 | obj = jqElem.data("idleTimerObj") || {},
41 |
42 | /* (intentionally not documented)
43 | * Toggles the idle state and fires an appropriate event.
44 | * @return {void}
45 | */
46 | toggleIdleState = function (e) {
47 | var obj = $.data(elem, "idleTimerObj") || {};
48 |
49 | // toggle the state
50 | obj.idle = !obj.idle;
51 |
52 | // store toggle state date time
53 | obj.olddate = +new Date();
54 |
55 | // create a custom event, with state and name space
56 | var event = $.Event((obj.idle ? "idle" : "active") + ".idleTimer");
57 |
58 | // trigger event on object with elem and copy of obj
59 | $(elem).trigger(event, [elem, $.extend({}, obj), e]);
60 | },
61 | /**
62 | * Handle event triggers
63 | * @return {void}
64 | * @method event
65 | * @static
66 | */
67 | handleEvent = function (e) {
68 | var obj = $.data(elem, "idleTimerObj") || {};
69 |
70 | // ignore writting to storage unless related to idleTimer
71 | if (e.type === "storage" && e.originalEvent.key !== obj.timerSyncId) {
72 | return;
73 | }
74 |
75 | // this is already paused, ignore events for now
76 | if (obj.remaining != null) { return; }
77 |
78 | /*
79 | mousemove is kinda buggy, it can be triggered when it should be idle.
80 | Typically is happening between 115 - 150 milliseconds after idle triggered.
81 | @psyafter & @kaellis report "always triggered if using modal (jQuery ui, with overlay)"
82 | @thorst has similar issues on ios7 "after $.scrollTop() on text area"
83 | */
84 | if (e.type === "mousemove") {
85 | // if coord are same, it didn't move
86 | if (e.pageX === obj.pageX && e.pageY === obj.pageY) {
87 | return;
88 | }
89 | // if coord don't exist how could it move
90 | if (typeof e.pageX === "undefined" && typeof e.pageY === "undefined") {
91 | return;
92 | }
93 | // under 200 ms is hard to do, and you would have to stop, as continuous activity will bypass this
94 | var elapsed = (+new Date()) - obj.olddate;
95 | if (elapsed < 200) {
96 | return;
97 | }
98 | }
99 |
100 | // clear any existing timeout
101 | clearTimeout(obj.tId);
102 |
103 | // if the idle timer is enabled, flip
104 | if (obj.idle) {
105 | toggleIdleState(e);
106 | }
107 |
108 | // store when user was last active
109 | obj.lastActive = +new Date();
110 |
111 | // update mouse coord
112 | obj.pageX = e.pageX;
113 | obj.pageY = e.pageY;
114 |
115 | // sync lastActive
116 | if (e.type !== "storage" && obj.timerSyncId) {
117 | if (typeof(localStorage) !== "undefined") {
118 | localStorage.setItem(obj.timerSyncId, obj.lastActive);
119 | }
120 | }
121 |
122 | // set a new timeout
123 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
124 | },
125 | /**
126 | * Restore initial settings and restart timer
127 | * @return {void}
128 | * @method reset
129 | * @static
130 | */
131 | reset = function () {
132 |
133 | var obj = $.data(elem, "idleTimerObj") || {};
134 |
135 | // reset settings
136 | obj.idle = obj.idleBackup;
137 | obj.olddate = +new Date();
138 | obj.lastActive = obj.olddate;
139 | obj.remaining = null;
140 |
141 | // reset Timers
142 | clearTimeout(obj.tId);
143 | if (!obj.idle) {
144 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
145 | }
146 |
147 | },
148 | /**
149 | * Store remaining time, stop timer
150 | * You can pause from an idle OR active state
151 | * @return {void}
152 | * @method pause
153 | * @static
154 | */
155 | pause = function () {
156 |
157 | var obj = $.data(elem, "idleTimerObj") || {};
158 |
159 | // this is already paused
160 | if ( obj.remaining != null ) { return; }
161 |
162 | // define how much is left on the timer
163 | obj.remaining = obj.timeout - ((+new Date()) - obj.olddate);
164 |
165 | // clear any existing timeout
166 | clearTimeout(obj.tId);
167 | },
168 | /**
169 | * Start timer with remaining value
170 | * @return {void}
171 | * @method resume
172 | * @static
173 | */
174 | resume = function () {
175 |
176 | var obj = $.data(elem, "idleTimerObj") || {};
177 |
178 | // this isn't paused yet
179 | if ( obj.remaining == null ) { return; }
180 |
181 | // start timer
182 | if ( !obj.idle ) {
183 | obj.tId = setTimeout(toggleIdleState, obj.remaining);
184 | }
185 |
186 | // clear remaining
187 | obj.remaining = null;
188 | },
189 | /**
190 | * Stops the idle timer. This removes appropriate event handlers
191 | * and cancels any pending timeouts.
192 | * @return {void}
193 | * @method destroy
194 | * @static
195 | */
196 | destroy = function () {
197 |
198 | var obj = $.data(elem, "idleTimerObj") || {};
199 |
200 | //clear any pending timeouts
201 | clearTimeout(obj.tId);
202 |
203 | //Remove data
204 | jqElem.removeData("idleTimerObj");
205 |
206 | //detach the event handlers
207 | jqElem.off("._idleTimer");
208 | },
209 | /**
210 | * Returns the time until becoming idle
211 | * @return {number}
212 | * @method remainingtime
213 | * @static
214 | */
215 | remainingtime = function () {
216 |
217 | var obj = $.data(elem, "idleTimerObj") || {};
218 |
219 | //If idle there is no time remaining
220 | if ( obj.idle ) { return 0; }
221 |
222 | //If its paused just return that
223 | if ( obj.remaining != null ) { return obj.remaining; }
224 |
225 | //Determine remaining, if negative idle didn't finish flipping, just return 0
226 | var remaining = obj.timeout - ((+new Date()) - obj.lastActive);
227 | if (remaining < 0) { remaining = 0; }
228 |
229 | //If this is paused return that number, else return current remaining
230 | return remaining;
231 | };
232 |
233 |
234 | // determine which function to call
235 | if (firstParam === null && typeof obj.idle !== "undefined") {
236 | // they think they want to init, but it already is, just reset
237 | reset();
238 | return jqElem;
239 | } else if (firstParam === null) {
240 | // they want to init
241 | } else if (firstParam !== null && typeof obj.idle === "undefined") {
242 | // they want to do something, but it isnt init
243 | // not sure the best way to handle this
244 | return false;
245 | } else if (firstParam === "destroy") {
246 | destroy();
247 | return jqElem;
248 | } else if (firstParam === "pause") {
249 | pause();
250 | return jqElem;
251 | } else if (firstParam === "resume") {
252 | resume();
253 | return jqElem;
254 | } else if (firstParam === "reset") {
255 | reset();
256 | return jqElem;
257 | } else if (firstParam === "getRemainingTime") {
258 | return remainingtime();
259 | } else if (firstParam === "getElapsedTime") {
260 | return (+new Date()) - obj.olddate;
261 | } else if (firstParam === "getLastActiveTime") {
262 | return obj.lastActive;
263 | } else if (firstParam === "isIdle") {
264 | return obj.idle;
265 | }
266 |
267 | // Test via a getter in the options object to see if the passive property is accessed
268 | // This isnt working in jquery, though is planned for 4.0
269 | // https://github.com/jquery/jquery/issues/2871
270 | /*var supportsPassive = false;
271 | try {
272 | var Popts = Object.defineProperty({}, "passive", {
273 | get: function() {
274 | supportsPassive = true;
275 | }
276 | });
277 | window.addEventListener("test", null, Popts);
278 | } catch (e) {}
279 | */
280 |
281 | /* (intentionally not documented)
282 | * Handles a user event indicating that the user isn't idle. namespaced with internal idleTimer
283 | * @param {Event} event A DOM2-normalized event object.
284 | * @return {void}
285 | */
286 | jqElem.on((opts.events + " ").split(" ").join("._idleTimer ").trim(), function (e) {
287 | handleEvent(e);
288 | });
289 | //}, supportsPassive ? { passive: true } : false);
290 |
291 | if (opts.timerSyncId) {
292 | $(window).on("storage", handleEvent);
293 | }
294 |
295 | // Internal Object Properties, This isn't all necessary, but we
296 | // explicitly define all keys here so we know what we are working with
297 | obj = $.extend({}, {
298 | olddate : +new Date(), // the last time state changed
299 | lastActive: +new Date(), // the last time timer was active
300 | idle : opts.idle, // current state
301 | idleBackup : opts.idle, // backup of idle parameter since it gets modified
302 | timeout : opts.timeout, // the interval to change state
303 | remaining : null, // how long until state changes
304 | timerSyncId : opts.timerSyncId, // localStorage key to use for syncing this timer
305 | tId : null, // the idle timer setTimeout
306 | pageX : null, // used to store the mouse coord
307 | pageY : null
308 | });
309 |
310 | // set a timeout to toggle state. May wish to omit this in some situations
311 | if (!obj.idle) {
312 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
313 | }
314 |
315 | // store our instance on the object
316 | $.data(elem, "idleTimerObj", obj);
317 |
318 | return jqElem;
319 | };
320 |
321 | // This allows binding to element
322 | $.fn.idleTimer = function (firstParam) {
323 | if (this[0]) {
324 | return $.idleTimer(firstParam, this[0]);
325 | }
326 |
327 | return this;
328 | };
329 |
330 | })(jQuery);
331 |
--------------------------------------------------------------------------------
/dist/idle-timer.min.js:
--------------------------------------------------------------------------------
1 | /*! Idle Timer v1.1.1 2020-06-25 | https://github.com/thorst/jquery-idletimer | (c) 2020 Paul Irish | Licensed MIT */
2 |
3 | !function(c){c.idleTimer=function(e,n){var i;"object"==typeof e?(i=e,e=null):"number"==typeof e&&(i={timeout:e},e=null),n=n||document,i=c.extend({idle:!1,timeout:3e4,events:"mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove"},i);function t(e){var i=c.data(n,"idleTimerObj")||{};i.idle=!i.idle,i.olddate=+new Date;var t=c.Event((i.idle?"idle":"active")+".idleTimer");c(n).trigger(t,[n,c.extend({},i),e])}function r(e){var i=c.data(n,"idleTimerObj")||{};if(("storage"!==e.type||e.originalEvent.key===i.timerSyncId)&&null==i.remaining){if("mousemove"===e.type){if(e.pageX===i.pageX&&e.pageY===i.pageY)return;if(void 0===e.pageX&&void 0===e.pageY)return;if(new Date-i.olddate<200)return}clearTimeout(i.tId),i.idle&&t(e),i.lastActive=+new Date,i.pageX=e.pageX,i.pageY=e.pageY,"storage"!==e.type&&i.timerSyncId&&"undefined"!=typeof localStorage&&localStorage.setItem(i.timerSyncId,i.lastActive),i.tId=setTimeout(t,i.timeout)}}function l(){var e=c.data(n,"idleTimerObj")||{};e.idle=e.idleBackup,e.olddate=+new Date,e.lastActive=e.olddate,e.remaining=null,clearTimeout(e.tId),e.idle||(e.tId=setTimeout(t,e.timeout))}var a,d,o,u=c(n),m=u.data("idleTimerObj")||{};if(null===e&&void 0!==m.idle)return l(),u;if(null!==e){if(null!==e&&void 0===m.idle)return!1;if("destroy"===e)return o=c.data(n,"idleTimerObj")||{},clearTimeout(o.tId),u.removeData("idleTimerObj"),u.off("._idleTimer"),u;if("pause"===e)return null==(d=c.data(n,"idleTimerObj")||{}).remaining&&(d.remaining=d.timeout-(new Date-d.olddate),clearTimeout(d.tId)),u;if("resume"===e)return null!=(a=c.data(n,"idleTimerObj")||{}).remaining&&(a.idle||(a.tId=setTimeout(t,a.remaining)),a.remaining=null),u;if("reset"===e)return l(),u;if("getRemainingTime"===e)return function(){var e=c.data(n,"idleTimerObj")||{};if(e.idle)return 0;if(null!=e.remaining)return e.remaining;var i=e.timeout-(new Date-e.lastActive);return i<0&&(i=0),i}();if("getElapsedTime"===e)return new Date-m.olddate;if("getLastActiveTime"===e)return m.lastActive;if("isIdle"===e)return m.idle}return u.on((i.events+" ").split(" ").join("._idleTimer ").trim(),function(e){r(e)}),i.timerSyncId&&c(window).on("storage",r),(m=c.extend({},{olddate:+new Date,lastActive:+new Date,idle:i.idle,idleBackup:i.idle,timeout:i.timeout,remaining:null,timerSyncId:i.timerSyncId,tId:null,pageX:null,pageY:null})).idle||(m.tId=setTimeout(t,m.timeout)),c.data(n,"idleTimerObj",m),u},c.fn.idleTimer=function(e){return this[0]?c.idleTimer(e,this[0]):this}}(jQuery);
--------------------------------------------------------------------------------
/idle-timer.jquery.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "idle-timer",
3 | "title": "Idle Timer",
4 | "description": "provides you a way to monitor user activity with a page.",
5 | "version": "1.1.1",
6 | "homepage": "https://github.com/thorst/jquery-idletimer",
7 | "author": {
8 | "name": "Paul Irish",
9 | "email": "paul.irish@gmail.com"
10 | },
11 | "maintainers": [
12 | {
13 | "name": "Mike Sherov",
14 | "email": "mike.sherov@gmail.com"
15 | },
16 | {
17 | "name": "Todd Horst",
18 | "email": "toddmhorst@yahoo.com"
19 | }
20 | ],
21 | "repository": {
22 | "type": "git",
23 | "url": "git://github.com/thorst/jquery-idletimer.git"
24 | },
25 | "bugs": "https://github.com/thorst/jquery-idletimer/issues",
26 | "licenses": [
27 | {
28 | "type": "MIT",
29 | "url": "https://github.com/thorst/jquery-idletimer/blob/master/LICENSE-MIT"
30 | }
31 | ],
32 | "dependencies": {
33 | "jquery": "1.7"
34 | },
35 | "devDependencies": {
36 | "grunt": "^1.1.0",
37 | "grunt-contrib-concat": "^1.0.1",
38 | "grunt-contrib-jshint": "^2.1.0",
39 | "grunt-contrib-qunit": "^4.0.0",
40 | "grunt-contrib-uglify": "^4.0.1",
41 | "grunt-contrib-watch": "^1.1.0"
42 | },
43 | "keywords": []
44 | }
45 |
--------------------------------------------------------------------------------
/jquery-idletimer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.21005.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "jquery-idletimer", "http://localhost:3751", "{70FF000C-3D87-429F-86E5-C99C2CA464E0}"
7 | ProjectSection(WebsiteProperties) = preProject
8 | UseIISExpress = "true"
9 | TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0"
10 | Debug.AspNetCompiler.VirtualPath = "/localhost_3751"
11 | Debug.AspNetCompiler.PhysicalPath = "..\..\..\GitHub\jquery-idletimer\"
12 | Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_3751\"
13 | Debug.AspNetCompiler.Updateable = "true"
14 | Debug.AspNetCompiler.ForceOverwrite = "true"
15 | Debug.AspNetCompiler.FixedNames = "false"
16 | Debug.AspNetCompiler.Debug = "True"
17 | Release.AspNetCompiler.VirtualPath = "/localhost_3751"
18 | Release.AspNetCompiler.PhysicalPath = "..\..\..\GitHub\jquery-idletimer\"
19 | Release.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_3751\"
20 | Release.AspNetCompiler.Updateable = "true"
21 | Release.AspNetCompiler.ForceOverwrite = "true"
22 | Release.AspNetCompiler.FixedNames = "false"
23 | Release.AspNetCompiler.Debug = "False"
24 | SlnRelativePath = "..\..\..\GitHub\jquery-idletimer\"
25 | EndProjectSection
26 | EndProject
27 | Global
28 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
29 | Debug|Any CPU = Debug|Any CPU
30 | EndGlobalSection
31 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
32 | {70FF000C-3D87-429F-86E5-C99C2CA464E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {70FF000C-3D87-429F-86E5-C99C2CA464E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | EndGlobalSection
35 | GlobalSection(SolutionProperties) = preSolution
36 | HideSolutionNode = FALSE
37 | EndGlobalSection
38 | EndGlobal
39 |
--------------------------------------------------------------------------------
/jquery-idletimer.v12.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thorst/jquery-idletimer/d52354c25ff688fe16550338bbac9c69218b1326/jquery-idletimer.v12.suo
--------------------------------------------------------------------------------
/libs/jquery-loader.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | // Default to the local version.
3 | var path = '../libs/jquery/jquery.js';
4 | // Get any jquery=___ param from the query string.
5 | var jqversion = location.search.match(/[?&]jquery=(.*?)(?=&|$)/);
6 | // If a version was specified, use that version from code.jquery.com.
7 | if (jqversion) {
8 | path = 'http://code.jquery.com/jquery-' + jqversion[1] + '.js';
9 | }
10 | // This is the only time I'll ever use document.write, I promise!
11 | document.write('');
12 | }());
13 |
--------------------------------------------------------------------------------
/libs/qunit/qunit.css:
--------------------------------------------------------------------------------
1 | /**
2 | * QUnit v1.4.0 - A JavaScript Unit Testing Framework
3 | *
4 | * http://docs.jquery.com/QUnit
5 | *
6 | * Copyright (c) 2012 John Resig, Jörn Zaefferer
7 | * Dual licensed under the MIT (MIT-LICENSE.txt)
8 | * or GPL (GPL-LICENSE.txt) licenses.
9 | */
10 |
11 | /** Font Family and Sizes */
12 |
13 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
14 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
15 | }
16 |
17 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
18 | #qunit-tests { font-size: smaller; }
19 |
20 |
21 | /** Resets */
22 |
23 | #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
24 | margin: 0;
25 | padding: 0;
26 | }
27 |
28 |
29 | /** Header */
30 |
31 | #qunit-header {
32 | padding: 0.5em 0 0.5em 1em;
33 |
34 | color: #8699a4;
35 | background-color: #0d3349;
36 |
37 | font-size: 1.5em;
38 | line-height: 1em;
39 | font-weight: normal;
40 |
41 | border-radius: 15px 15px 0 0;
42 | -moz-border-radius: 15px 15px 0 0;
43 | -webkit-border-top-right-radius: 15px;
44 | -webkit-border-top-left-radius: 15px;
45 | }
46 |
47 | #qunit-header a {
48 | text-decoration: none;
49 | color: #c2ccd1;
50 | }
51 |
52 | #qunit-header a:hover,
53 | #qunit-header a:focus {
54 | color: #fff;
55 | }
56 |
57 | #qunit-header label {
58 | display: inline-block;
59 | }
60 |
61 | #qunit-banner {
62 | height: 5px;
63 | }
64 |
65 | #qunit-testrunner-toolbar {
66 | padding: 0.5em 0 0.5em 2em;
67 | color: #5E740B;
68 | background-color: #eee;
69 | }
70 |
71 | #qunit-userAgent {
72 | padding: 0.5em 0 0.5em 2.5em;
73 | background-color: #2b81af;
74 | color: #fff;
75 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
76 | }
77 |
78 |
79 | /** Tests: Pass/Fail */
80 |
81 | #qunit-tests {
82 | list-style-position: inside;
83 | }
84 |
85 | #qunit-tests li {
86 | padding: 0.4em 0.5em 0.4em 2.5em;
87 | border-bottom: 1px solid #fff;
88 | list-style-position: inside;
89 | }
90 |
91 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
92 | display: none;
93 | }
94 |
95 | #qunit-tests li strong {
96 | cursor: pointer;
97 | }
98 |
99 | #qunit-tests li a {
100 | padding: 0.5em;
101 | color: #c2ccd1;
102 | text-decoration: none;
103 | }
104 | #qunit-tests li a:hover,
105 | #qunit-tests li a:focus {
106 | color: #000;
107 | }
108 |
109 | #qunit-tests ol {
110 | margin-top: 0.5em;
111 | padding: 0.5em;
112 |
113 | background-color: #fff;
114 |
115 | border-radius: 15px;
116 | -moz-border-radius: 15px;
117 | -webkit-border-radius: 15px;
118 |
119 | box-shadow: inset 0px 2px 13px #999;
120 | -moz-box-shadow: inset 0px 2px 13px #999;
121 | -webkit-box-shadow: inset 0px 2px 13px #999;
122 | }
123 |
124 | #qunit-tests table {
125 | border-collapse: collapse;
126 | margin-top: .2em;
127 | }
128 |
129 | #qunit-tests th {
130 | text-align: right;
131 | vertical-align: top;
132 | padding: 0 .5em 0 0;
133 | }
134 |
135 | #qunit-tests td {
136 | vertical-align: top;
137 | }
138 |
139 | #qunit-tests pre {
140 | margin: 0;
141 | white-space: pre-wrap;
142 | word-wrap: break-word;
143 | }
144 |
145 | #qunit-tests del {
146 | background-color: #e0f2be;
147 | color: #374e0c;
148 | text-decoration: none;
149 | }
150 |
151 | #qunit-tests ins {
152 | background-color: #ffcaca;
153 | color: #500;
154 | text-decoration: none;
155 | }
156 |
157 | /*** Test Counts */
158 |
159 | #qunit-tests b.counts { color: black; }
160 | #qunit-tests b.passed { color: #5E740B; }
161 | #qunit-tests b.failed { color: #710909; }
162 |
163 | #qunit-tests li li {
164 | margin: 0.5em;
165 | padding: 0.4em 0.5em 0.4em 0.5em;
166 | background-color: #fff;
167 | border-bottom: none;
168 | list-style-position: inside;
169 | }
170 |
171 | /*** Passing Styles */
172 |
173 | #qunit-tests li li.pass {
174 | color: #5E740B;
175 | background-color: #fff;
176 | border-left: 26px solid #C6E746;
177 | }
178 |
179 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
180 | #qunit-tests .pass .test-name { color: #366097; }
181 |
182 | #qunit-tests .pass .test-actual,
183 | #qunit-tests .pass .test-expected { color: #999999; }
184 |
185 | #qunit-banner.qunit-pass { background-color: #C6E746; }
186 |
187 | /*** Failing Styles */
188 |
189 | #qunit-tests li li.fail {
190 | color: #710909;
191 | background-color: #fff;
192 | border-left: 26px solid #EE5757;
193 | white-space: pre;
194 | }
195 |
196 | #qunit-tests > li:last-child {
197 | border-radius: 0 0 15px 15px;
198 | -moz-border-radius: 0 0 15px 15px;
199 | -webkit-border-bottom-right-radius: 15px;
200 | -webkit-border-bottom-left-radius: 15px;
201 | }
202 |
203 | #qunit-tests .fail { color: #000000; background-color: #EE5757; }
204 | #qunit-tests .fail .test-name,
205 | #qunit-tests .fail .module-name { color: #000000; }
206 |
207 | #qunit-tests .fail .test-actual { color: #EE5757; }
208 | #qunit-tests .fail .test-expected { color: green; }
209 |
210 | #qunit-banner.qunit-fail { background-color: #EE5757; }
211 |
212 |
213 | /** Result */
214 |
215 | #qunit-testresult {
216 | padding: 0.5em 0.5em 0.5em 2.5em;
217 |
218 | color: #2b81af;
219 | background-color: #D2E0E6;
220 |
221 | border-bottom: 1px solid white;
222 | }
223 |
224 | /** Fixture */
225 |
226 | #qunit-fixture {
227 | position: absolute;
228 | top: -10000px;
229 | left: -10000px;
230 | width: 1000px;
231 | height: 1000px;
232 | }
233 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery-idletimer",
3 | "main": "dist/idle-timer.js",
4 | "version": "1.1.1",
5 | "engines": {
6 | "node": ">= 10.0.0"
7 | },
8 | "scripts": {
9 | "test": "grunt qunit"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git://github.com/thorst/jquery-idletimer.git"
14 | },
15 | "devDependencies": {
16 | "grunt": "^1.1.0",
17 | "grunt-contrib-concat": "^1.0.1",
18 | "grunt-contrib-jshint": "^2.1.0",
19 | "grunt-contrib-qunit": "^4.0.0",
20 | "grunt-contrib-uglify": "^4.0.1",
21 | "grunt-contrib-watch": "^1.1.0"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "curly": true,
3 | "eqeqeq": true,
4 | "immed": true,
5 | "latedef": true,
6 | "newcap": true,
7 | "noarg": true,
8 | "sub": true,
9 | "undef": true,
10 | "unused": true,
11 | "boss": true,
12 | "eqnull": true,
13 | "browser": true,
14 | "quotmark": "double",
15 | "predef": ["jQuery"]
16 | }
17 |
--------------------------------------------------------------------------------
/src/idle-timer.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2009 Nicholas C. Zakas
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sub-license, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | * THE SOFTWARE.
21 | */
22 | /*
23 | mousewheel (deprecated) -> IE6.0, Chrome, Opera, Safari
24 | DOMMouseScroll (deprecated) -> Firefox 1.0
25 | wheel (standard) -> Chrome 31, Firefox 17, IE9, Firefox Mobile 17.0
26 |
27 | //No need to use, use DOMMouseScroll
28 | MozMousePixelScroll -> Firefox 3.5, Firefox Mobile 1.0
29 |
30 | //Events
31 | WheelEvent -> see wheel
32 | MouseWheelEvent -> see mousewheel
33 | MouseScrollEvent -> Firefox 3.5, Firefox Mobile 1.0
34 | */
35 | (function ($) {
36 |
37 | $.idleTimer = function (firstParam, elem, uniqueId) {
38 | var opts;
39 | if ( typeof firstParam === "object" ) {
40 | opts = firstParam;
41 | firstParam = null;
42 | } else if (typeof firstParam === "number") {
43 | opts = { timeout: firstParam };
44 | firstParam = null;
45 | }
46 |
47 | // element to watch
48 | elem = elem || document;
49 |
50 | uniqueId = uniqueId || "";
51 |
52 | // defaults that are to be stored as instance props on the elem
53 | opts = $.extend({
54 | idle: false, // indicates if the user is idle
55 | timeout: 30000, // the amount of time (ms) before the user is considered idle
56 | events: "mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove" // define active events
57 | }, opts);
58 |
59 | var jqElem = $(elem),
60 | obj = jqElem.data("idleTimerObj" + uniqueId) || {},
61 |
62 | /* (intentionally not documented)
63 | * Toggles the idle state and fires an appropriate event.
64 | * @return {void}
65 | */
66 | toggleIdleState = function (e) {
67 | var obj = $.data(elem, "idleTimerObj" + uniqueId) || {};
68 |
69 | // toggle the state
70 | obj.idle = !obj.idle;
71 |
72 | // store toggle state date time
73 | obj.olddate = +new Date();
74 |
75 | // create a custom event, with state and name space
76 | var event = $.Event((obj.idle ? "idle" : "active") + ".idleTimer" + uniqueId);
77 |
78 | // trigger event on object with elem and copy of obj
79 | $(elem).trigger(event, [elem, $.extend({}, obj), e]);
80 | },
81 | /**
82 | * Handle event triggers
83 | * @return {void}
84 | * @method event
85 | * @static
86 | */
87 | handleEvent = function (e) {
88 |
89 | var obj = $.data(elem, "idleTimerObj" + uniqueId) || {};
90 |
91 | // ignore writting to storage unless related to idleTimer
92 | if (e.type === "storage" && e.originalEvent.key !== obj.timerSyncId) {
93 | return;
94 | }
95 |
96 | // this is already paused, ignore events for now
97 | if (obj.remaining != null) { return; }
98 |
99 | /*
100 | mousemove is kinda buggy, it can be triggered when it should be idle.
101 | Typically is happening between 115 - 150 milliseconds after idle triggered.
102 | @psyafter & @kaellis report "always triggered if using modal (jQuery ui, with overlay)"
103 | @thorst has similar issues on ios7 "after $.scrollTop() on text area"
104 | */
105 | if (e.type === "mousemove") {
106 | // if coord are same, it didn't move
107 | if (e.pageX === obj.pageX && e.pageY === obj.pageY) {
108 | return;
109 | }
110 | // if coord don't exist how could it move
111 | if (typeof e.pageX === "undefined" && typeof e.pageY === "undefined") {
112 | return;
113 | }
114 | // under 200 ms is hard to do, and you would have to stop, as continuous activity will bypass this
115 | var elapsed = (+new Date()) - obj.olddate;
116 | if (elapsed < 200) {
117 | return;
118 | }
119 | }
120 |
121 | // clear any existing timeout
122 | clearTimeout(obj.tId);
123 |
124 | // if the idle timer is enabled, flip
125 | if (obj.idle) {
126 | toggleIdleState(e);
127 | }
128 |
129 | // store when user was last active
130 | obj.lastActive = +new Date();
131 |
132 | // update mouse coord
133 | obj.pageX = e.pageX;
134 | obj.pageY = e.pageY;
135 |
136 | // sync lastActive
137 | if (e.type !== "storage" && obj.timerSyncId) {
138 | if (typeof(localStorage) !== "undefined") {
139 | localStorage.setItem(obj.timerSyncId, obj.lastActive);
140 | }
141 | }
142 |
143 | // set a new timeout
144 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
145 | },
146 | /**
147 | * Restore initial settings and restart timer
148 | * @return {void}
149 | * @method reset
150 | * @static
151 | */
152 | reset = function () {
153 |
154 | var obj = $.data(elem, "idleTimerObj" + uniqueId) || {};
155 |
156 | // reset settings
157 | obj.idle = obj.idleBackup;
158 | obj.olddate = +new Date();
159 | obj.lastActive = obj.olddate;
160 | obj.remaining = null;
161 |
162 | // reset Timers
163 | clearTimeout(obj.tId);
164 | if (!obj.idle) {
165 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
166 | }
167 |
168 | },
169 | /**
170 | * Store remaining time, stop timer
171 | * You can pause from an idle OR active state
172 | * @return {void}
173 | * @method pause
174 | * @static
175 | */
176 | pause = function () {
177 |
178 | var obj = $.data(elem, "idleTimerObj" + uniqueId) || {};
179 |
180 | // this is already paused
181 | if ( obj.remaining != null ) { return; }
182 |
183 | // define how much is left on the timer
184 | obj.remaining = obj.timeout - ((+new Date()) - obj.olddate);
185 |
186 | // clear any existing timeout
187 | clearTimeout(obj.tId);
188 | },
189 | /**
190 | * Start timer with remaining value
191 | * @return {void}
192 | * @method resume
193 | * @static
194 | */
195 | resume = function () {
196 |
197 | var obj = $.data(elem, "idleTimerObj" + uniqueId) || {};
198 |
199 | // this isn't paused yet
200 | if ( obj.remaining == null ) { return; }
201 |
202 | // start timer
203 | if ( !obj.idle ) {
204 | obj.tId = setTimeout(toggleIdleState, obj.remaining);
205 | }
206 |
207 | // clear remaining
208 | obj.remaining = null;
209 | },
210 | /**
211 | * Stops the idle timer. This removes appropriate event handlers
212 | * and cancels any pending timeouts.
213 | * @return {void}
214 | * @method destroy
215 | * @static
216 | */
217 | destroy = function () {
218 |
219 | var obj = $.data(elem, "idleTimerObj" + uniqueId) || {};
220 |
221 | //clear any pending timeouts
222 | clearTimeout(obj.tId);
223 |
224 | //Remove data
225 | jqElem.removeData("idleTimerObj" + uniqueId);
226 |
227 | //detach the event handlers
228 | jqElem.off("._idleTimer" + uniqueId);
229 | },
230 | /**
231 | * Returns the time until becoming idle
232 | * @return {number}
233 | * @method remainingtime
234 | * @static
235 | */
236 | remainingtime = function () {
237 |
238 | var obj = $.data(elem, "idleTimerObj" + uniqueId) || {};
239 |
240 | //If idle there is no time remaining
241 | if ( obj.idle ) { return 0; }
242 |
243 | //If its paused just return that
244 | if ( obj.remaining != null ) { return obj.remaining; }
245 |
246 | //Determine remaining, if negative idle didn't finish flipping, just return 0
247 | var remaining = obj.timeout - ((+new Date()) - obj.lastActive);
248 | if (remaining < 0) { remaining = 0; }
249 |
250 | //If this is paused return that number, else return current remaining
251 | return remaining;
252 | };
253 |
254 |
255 | // determine which function to call
256 | if (firstParam === null && typeof obj.idle !== "undefined") {
257 | // they think they want to init, but it already is, just reset
258 | reset();
259 | return jqElem;
260 | } else if (firstParam === null) {
261 | // they want to init
262 | } else if (firstParam !== null && typeof obj.idle === "undefined") {
263 | // they want to do something, but it isnt init
264 | // not sure the best way to handle this
265 | return false;
266 | } else if (firstParam === "destroy") {
267 | destroy();
268 | return jqElem;
269 | } else if (firstParam === "pause") {
270 | pause();
271 | return jqElem;
272 | } else if (firstParam === "resume") {
273 | resume();
274 | return jqElem;
275 | } else if (firstParam === "reset") {
276 | reset();
277 | return jqElem;
278 | } else if (firstParam === "getRemainingTime") {
279 | return remainingtime();
280 | } else if (firstParam === "getElapsedTime") {
281 | return (+new Date()) - obj.olddate;
282 | } else if (firstParam === "getLastActiveTime") {
283 | return obj.lastActive;
284 | } else if (firstParam === "isIdle") {
285 | return obj.idle;
286 | }
287 |
288 | // Test via a getter in the options object to see if the passive property is accessed
289 | // This isnt working in jquery, though is planned for 4.0
290 | // https://github.com/jquery/jquery/issues/2871
291 | /*var supportsPassive = false;
292 | try {
293 | var Popts = Object.defineProperty({}, "passive", {
294 | get: function() {
295 | supportsPassive = true;
296 | }
297 | });
298 | window.addEventListener("test", null, Popts);
299 | } catch (e) {}
300 | */
301 |
302 | /* (intentionally not documented)
303 | * Handles a user event indicating that the user isn't idle. namespaced with internal idleTimer
304 | * @param {Event} event A DOM2-normalized event object.
305 | * @return {void}
306 | */
307 | jqElem.on((opts.events + " ").split(" ").join("._idleTimer" + uniqueId + " ").trim(), function (e) {
308 |
309 | handleEvent(e);
310 | });
311 | //}, supportsPassive ? { passive: true } : false);
312 |
313 | if (opts.timerSyncId) {
314 | $(window).on("storage", handleEvent);
315 | }
316 |
317 | // Internal Object Properties, This isn't all necessary, but we
318 | // explicitly define all keys here so we know what we are working with
319 | obj = $.extend({}, {
320 | olddate : +new Date(), // the last time state changed
321 | lastActive: +new Date(), // the last time timer was active
322 | idle : opts.idle, // current state
323 | idleBackup : opts.idle, // backup of idle parameter since it gets modified
324 | timeout : opts.timeout, // the interval to change state
325 | remaining : null, // how long until state changes
326 | timerSyncId : opts.timerSyncId, // localStorage key to use for syncing this timer
327 | tId : null, // the idle timer setTimeout
328 | pageX : null, // used to store the mouse coord
329 | pageY : null
330 | });
331 |
332 | // set a timeout to toggle state. May wish to omit this in some situations
333 | if (!obj.idle) {
334 | obj.tId = setTimeout(toggleIdleState, obj.timeout);
335 | }
336 |
337 | // store our instance on the object
338 | $.data(elem, "idleTimerObj" + uniqueId, obj);
339 |
340 | return jqElem;
341 | };
342 |
343 | // This allows binding to element
344 | $.fn.idleTimer = function (firstParam, uniqueId) {
345 | if (this[0]) {
346 | return $.idleTimer(firstParam, this[0], uniqueId);
347 | }
348 |
349 | return this;
350 | };
351 |
352 | })(jQuery);
353 |
--------------------------------------------------------------------------------
/test/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "curly": true,
3 | "eqeqeq": true,
4 | "immed": true,
5 | "latedef": true,
6 | "newcap": true,
7 | "noarg": true,
8 | "sub": true,
9 | "undef": true,
10 | "unused": true,
11 | "boss": true,
12 | "eqnull": true,
13 | "browser": true,
14 | "quotmark": "double",
15 | "predef": [
16 | "jQuery",
17 | "QUnit",
18 | "module",
19 | "test",
20 | "asyncTest",
21 | "expect",
22 | "start",
23 | "stop",
24 | "ok",
25 | "equal",
26 | "notEqual",
27 | "deepEqual",
28 | "notDeepEqual",
29 | "strictEqual",
30 | "notStrictEqual",
31 | "raises"
32 | ]
33 | }
--------------------------------------------------------------------------------
/test/idle-timer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Idle Timer Test Suite
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | lame test markup
27 | normal test markup
28 | awesome test markup
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/test/idle-timer_test.js:
--------------------------------------------------------------------------------
1 | (function($) {
2 | /*
3 | ======== A Handy Little QUnit Reference ========
4 | http://docs.jquery.com/QUnit
5 |
6 | Test methods:
7 | expect(numAssertions)
8 | stop(increment)
9 | start(decrement)
10 | Test assertions:
11 | ok(value, [message])
12 | equal(actual, expected, [message])
13 | notEqual(actual, expected, [message])
14 | deepEqual(actual, expected, [message])
15 | notDeepEqual(actual, expected, [message])
16 | strictEqual(actual, expected, [message])
17 | notStrictEqual(actual, expected, [message])
18 | raises(block, [expected], [message])
19 | */
20 | //Name | expects | test
21 | module("Events Auto Binding");
22 | asyncTest("idle Event Triggered", 2, function () {
23 | $(document).on("idle.idleTimer", function (event, elem, obj) {
24 |
25 | ok(true, "idle fires at document");
26 | ok(obj.idle, "object returned properly");
27 |
28 | $.idleTimer("destroy");
29 | $(document).off();
30 |
31 | start();
32 | });
33 | $.idleTimer( 100 );
34 | });
35 | asyncTest("idle Event Triggered when using unique id", 2, function () {
36 | $(document).on("idle.idleTimersomeUniqueString", function (event, elem, obj) {
37 |
38 | ok(true, "idle fires at document");
39 | ok(obj.idle, "object returned properly");
40 |
41 | $.idleTimer("destroy", document, "someUniqueString");
42 | $(document).off();
43 |
44 | start();
45 | });
46 | $.idleTimer( 100, document, "someUniqueString" );
47 | });
48 | asyncTest( "active Event Triggered", 2, function() {
49 | $( document ).on( "active.idleTimer", function(event, elem, obj){
50 |
51 | ok(true, "active fires at document");
52 | ok(!obj.idle, "object returned properly");
53 |
54 | $.idleTimer("destroy");
55 | $(document).off();
56 |
57 | start();
58 | });
59 | $.idleTimer({idle:true});
60 | setTimeout( function(){
61 | $( "#qunit-fixture" ).trigger( "keydown" );
62 | }, 100 );
63 | });
64 |
65 |
66 |
67 |
68 | module("Events Element Binding");
69 | asyncTest("idle Triggered", 2, function () {
70 | $("#qunit-fixture").on("idle.idleTimer", function (event, elem, obj) {
71 |
72 | ok(true, "idle fires at document");
73 | ok(obj.idle, "object returned properly");
74 |
75 | $("#qunit-fixture").idleTimer("destroy");
76 |
77 | start();
78 | });
79 | $("#qunit-fixture").idleTimer(100);
80 | });
81 | asyncTest("idle Triggered with multiple idle timers", 4, function () {
82 | var oneFinished = false;
83 | $("#qunit-fixture").on("idle.idleTimersomeUniqueString", function (event, elem, obj) {
84 |
85 | ok(true, "idle fires at document");
86 | ok(obj.idle, "object returned properly");
87 |
88 | $("#qunit-fixture").idleTimer("destroy", "someUniqueString");
89 |
90 | if (oneFinished) {
91 | start();
92 | }
93 | oneFinished = true;
94 | });
95 | $("#qunit-fixture").on("idle.idleTimeranotherUniqueString", function (event, elem, obj) {
96 |
97 | ok(true, "idle fires at document");
98 | ok(obj.idle, "object returned properly");
99 |
100 | $("#qunit-fixture").idleTimer("destroy", "anotherUniqueString");
101 |
102 | if (oneFinished) {
103 | start();
104 | }
105 | oneFinished = true;
106 | });
107 | $("#qunit-fixture").idleTimer(100, "someUniqueString");
108 | $("#qunit-fixture").idleTimer(100, "anotherUniqueString");
109 | });
110 | asyncTest("active Triggered", 2, function () {
111 | $("#qunit-fixture").on("active.idleTimer", function (event, elem, obj) {
112 |
113 | ok(true, "active fires at document");
114 | ok(!obj.idle, "object returned properly");
115 |
116 | $("#qunit-fixture").idleTimer("destroy");
117 |
118 | start();
119 | });
120 | $("#qunit-fixture").idleTimer({ idle: true });
121 | setTimeout(function () {
122 | $("#qunit-fixture").trigger("keydown");
123 | }, 100);
124 | });
125 |
126 | module("Timer sync");
127 | asyncTest("setting lastActive via localStorage", 1, function() {
128 | localStorage.clear();
129 | $.idleTimer( {timeout: 500, timerSyncId: "timer-test"} );
130 | setTimeout( function() {
131 | $( "#qunit-fixture" ).trigger( "keydown" );
132 | }, 100 );
133 | setTimeout( function() {
134 | ok(localStorage.getItem("timer-test"), "localStorage key was set");
135 | $.idleTimer("destroy");
136 | $(document).off();
137 | start();
138 | }, 300 );
139 | });
140 | asyncTest( "storage triggers active", 2, function() {
141 | localStorage.clear();
142 | $( document ).on( "active.idleTimer", function(event, elem, obj){
143 |
144 | ok(true, "active fires at document");
145 | ok(!obj.idle, "object returned properly");
146 |
147 | $.idleTimer("destroy");
148 | $(document).off();
149 |
150 | start();
151 | });
152 | $.idleTimer( {idle:true, timerSyncId: "timer-storage-event-test"} );
153 | setTimeout( function() {
154 | var e = $.Event("storage");
155 | // simulate a storage event for this timer's sync ID
156 | e.originalEvent = {
157 | key: "timer-storage-event-test",
158 | oldValue: "1",
159 | newValue: "2"
160 | };
161 | $(window).trigger(e);
162 | }, 100 );
163 | });
164 | asyncTest( "storage triggers active on matching timerSyncId, unique id does not matter", 4, function() {
165 | localStorage.clear();
166 | var oneFinished = false;
167 | $( document ).on( "active.idleTimersomeUniqueString", function(event, elem, obj){
168 |
169 | ok(true, "active fires at document");
170 | ok(!obj.idle, "object returned properly");
171 |
172 | if (oneFinished) {
173 | $.idleTimer("destroy", "someUniqueString");
174 | $(document).off();
175 | start();
176 | }
177 | oneFinished = true;
178 | });
179 | $( document ).on( "active.idleTimeranotherUniqueString", function(event, elem, obj){
180 |
181 | ok(true, "active fires at document");
182 | ok(!obj.idle, "object returned properly");
183 |
184 |
185 | if (oneFinished) {
186 | $.idleTimer("destroy", "anotherUniqueString");
187 | $(document).off();
188 | start();
189 | }
190 | oneFinished = true;
191 | });
192 | $.idleTimer( {idle:true, timerSyncId: "timer-storage-event-test"}, document, "someUniqueString");
193 | $.idleTimer( {idle:true, timerSyncId: "timer-storage-event-test"}, document, "anotherUniqueString");
194 | setTimeout( function() {
195 | var e = $.Event("storage");
196 | // simulate a storage event for this timer's sync ID
197 | e.originalEvent = {
198 | key: "timer-storage-event-test",
199 | oldValue: "1",
200 | newValue: "2"
201 | };
202 | $(window).trigger(e);
203 | }, 100 );
204 | });
205 |
206 | /*
207 | Need to actually test pause/resume/reset, not just thier return type
208 | */
209 | module("Functional");
210 | asyncTest("Pause works and is a jQuery instance", 4, function () {
211 |
212 | $.idleTimer(100);
213 | equal(typeof $.idleTimer( "pause" ).jquery , "string", "pause should be jquery" );
214 |
215 | $.idleTimer("resume");
216 | equal(typeof $(document).idleTimer("pause").jquery, "string", "pause should be jquery");
217 |
218 | setTimeout(function () {
219 | ok(!$.idleTimer("isIdle"), "timer still active");
220 | ok(!$(document).idleTimer("isIdle"), "timer still active");
221 |
222 | $.idleTimer("destroy");
223 | $(document).off();
224 |
225 | start();
226 | }, 200);
227 | });
228 |
229 |
230 |
231 | asyncTest("Resume works and is a jQuery instance", 4, function () {
232 |
233 | $.idleTimer(100);
234 |
235 | $.idleTimer("pause");
236 | equal(typeof $.idleTimer("resume").jquery, "string", "resume should be jquery");
237 |
238 | $.idleTimer("pause");
239 | equal(typeof $(document).idleTimer("resume").jquery, "string", "resume should be jquery");
240 |
241 | setTimeout(function () {
242 | ok($.idleTimer("isIdle"), "timer inactive");
243 | ok($(document).idleTimer("isIdle"), "timer inactive");
244 |
245 | $.idleTimer("destroy");
246 | $(document).off();
247 |
248 | start();
249 | }, 200);
250 | });
251 |
252 | asyncTest("Resume works and is a jQuery instance when using unique id", 4, function () {
253 |
254 | $.idleTimer(100, document, "someUniqueString");
255 |
256 | $.idleTimer("pause");
257 | equal(typeof $.idleTimer("resume", document, "someUniqueString").jquery, "string", "resume should be jquery");
258 |
259 | $.idleTimer("pause");
260 | equal(typeof $(document).idleTimer("resume", "someUniqueString").jquery, "string", "resume should be jquery");
261 |
262 | setTimeout(function () {
263 | ok($.idleTimer("isIdle", document, "someUniqueString"), "timer inactive");
264 | ok($(document).idleTimer("isIdle", "someUniqueString"), "timer inactive");
265 |
266 | $.idleTimer("destroy", "someUniqueString");
267 | $(document).off();
268 |
269 | start();
270 | }, 200);
271 | });
272 |
273 | test("Elapsed time is a number", 2, function () {
274 |
275 | $.idleTimer(100);
276 |
277 | equal(typeof $.idleTimer("getElapsedTime"), "number", "Elapsed time should be a number");
278 | equal(typeof $(document).idleTimer("getElapsedTime"), "number", "Elapsed time should be a number");
279 | });
280 |
281 | test("Init works and is a jQuery instance", 4, function () {
282 |
283 | equal(typeof $.idleTimer(100).jquery, "string", "Init should be jquery");
284 | equal(typeof $("#qunit-fixture").idleTimer(100).jquery, "string", "Destroy should be jquery");
285 |
286 | equal(typeof $(document).data("idleTimerObj").idle, "boolean", "Init data added");
287 | equal(typeof $("#qunit-fixture").data("idleTimerObj").idle, "boolean", "Init data added");
288 | });
289 |
290 | test("Destroy works and is a jQuery instance", 4, function () {
291 |
292 | $.idleTimer(100);
293 | $("#qunit-fixture").idleTimer(100);
294 |
295 | equal(typeof $.idleTimer("destroy").jquery, "string", "Destroy should be jquery");
296 | equal(typeof $("#qunit-fixture").idleTimer("destroy").jquery, "string", "Destroy should be jquery");
297 |
298 | equal(typeof $(document).data("idleTimerObj"), "undefined", "destroy removed data");
299 | equal(typeof $("#qunit-fixture").data("idleTimerObj"), "undefined", "destroy removed data");
300 | });
301 |
302 | asyncTest("Reset is a jQuery instance", 6, function () {
303 |
304 | //start the timer
305 | $.idleTimer(200);
306 | $.idleTimer("pause");
307 | $("#qunit-fixture").idleTimer(200);
308 | $("#qunit-fixture").idleTimer("pause");
309 |
310 | //After a bit, reset it
311 | setTimeout(function () {
312 | equal(typeof $.idleTimer("reset").jquery, "string", "reset should be jquery");
313 | equal(typeof $("#qunit-fixture").idleTimer("reset").jquery, "string", "reset should be jquery");
314 |
315 | ok($(document).data("idleTimerObj").remaining===null, "reset remaining");
316 | ok($("#qunit-fixture").data("idleTimerObj").remaining === null, "reset remaining");
317 | }, 100);
318 |
319 | setTimeout(function () {
320 | ok($.idleTimer("isIdle"), "timer inactive");
321 | ok($("#qunit-fixture").idleTimer("isIdle"), "timer inactive");
322 |
323 | $.idleTimer("destroy");
324 | $("#qunit-fixture").idleTimer("destroy");
325 | $(document).off();
326 |
327 | start();
328 | }, 400);
329 |
330 | });
331 |
332 | test("Last Active time is a number", 2, function () {
333 |
334 | $.idleTimer(100);
335 |
336 | equal(typeof $.idleTimer("getLastActiveTime"), "number", "Last Active time should be a number");
337 | equal(typeof $(document).idleTimer("getLastActiveTime"), "number", "Last Active time should be a number");
338 |
339 | $.idleTimer("destroy");
340 | });
341 |
342 | test("Remaining time is a number", 2, function () {
343 |
344 | $.idleTimer(100);
345 |
346 | equal( typeof $.idleTimer( "getRemainingTime" ), "number", "Remaining time should be a number" );
347 | equal(typeof $(document).idleTimer("getRemainingTime"), "number", "Remaining time should be a number");
348 |
349 | $.idleTimer("destroy");
350 | });
351 | test("isIdle is a boolean", 2, function () {
352 |
353 | $.idleTimer(100);
354 |
355 | equal(typeof $.idleTimer("isIdle"), "boolean", "isIdle should be a boolean");
356 | equal(typeof $(document).idleTimer("isIdle"), "boolean", "isIdle should be a boolean");
357 |
358 | $.idleTimer("destroy");
359 | });
360 |
361 | }(jQuery));
362 |
--------------------------------------------------------------------------------