From d0a9b34438de9ffd2c2b96fbd455d7c0c8458a3c Mon Sep 17 00:00:00 2001 From: Robert Malko Date: Mon, 16 Jan 2012 13:51:18 -0500 Subject: [PATCH 01/24] added prev_visit and time_since_last_visit to original_cookie for calculating when the last time somebody came to the page --- session.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/session.js b/session.js index 96775ab..3f2715b 100644 --- a/session.js +++ b/session.js @@ -31,7 +31,7 @@ var session_fetch = (function(win, doc, nav){ // Session cookie name (set blank to disable cookie) session_cookie: "first_session" }; - + // Session object var SessionRunner = function(){ // Helper for querying. @@ -103,8 +103,8 @@ var session_fetch = (function(win, doc, nav){ } } check_asynch(); }; - - + + // Browser (and OS) detection var browser = { detect: function(){ @@ -159,7 +159,7 @@ var session_fetch = (function(win, doc, nav){ { string: nav.userAgent, subString: "Android", identity: "Android" } ]} }; - + var modules = { browser: function(){ return browser.detect(); @@ -218,7 +218,7 @@ var session_fetch = (function(win, doc, nav){ silverlight: check_plugin("silverlight"), java: check_plugin("java"), quicktime: check_plugin("quicktime") - }; + }; }, session: function (cookie, expires){ var session = util.get_obj(cookie); @@ -257,11 +257,13 @@ var session_fetch = (function(win, doc, nav){ session.search.query = terms; session.search.terms = terms.split(" "); break; } - } + } } } else { + session.prev_visit = session.last_visit; session.last_visit = new Date().getTime(); session.visits++; + session.time_since_last_visit = session.last_visit - session.prev_visit; } util.set_cookie(cookie, util.package_obj(session), expires); return session; @@ -320,7 +322,7 @@ var session_fetch = (function(win, doc, nav){ util.embed_script("http://api.ipinfodb.com/v3/ip-city/?key=" + api_key + "&format=json&callback=ipinfocb"); }} }; - + // Utilities var util = { parse_url: function(url_str){ @@ -380,7 +382,7 @@ var session_fetch = (function(win, doc, nav){ } } }; - + // JSON var JSON = { parse: (win.JSON && win.JSON.parse) || function(data){ From 28e1835fd81d8e19cf8f6f71a7fd7b24541693ff Mon Sep 17 00:00:00 2001 From: Mattijs Hoitink Date: Mon, 23 Jan 2012 15:47:10 +0100 Subject: [PATCH 02/24] Typo in iPad os detection --- session.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/session.js b/session.js index 96775ab..8c40d2b 100644 --- a/session.js +++ b/session.js @@ -154,7 +154,7 @@ var session_fetch = (function(win, doc, nav){ { string: nav.platform, subString: "Win", identity: "Windows" }, { string: nav.platform, subString: "Mac", identity: "Mac" }, { string: nav.userAgent, subString: "iPhone", identity: "iPhone/iPod" }, - { string: nav.userAgent, subString: "iPad", identitiy: "iPad" }, + { string: nav.userAgent, subString: "iPad", identity: "iPad" }, { string: nav.platform, subString: "Linux", identity: "Linux" }, { string: nav.userAgent, subString: "Android", identity: "Android" } ]} From 126f49026b023171ace96f85d94363719bbbcb29 Mon Sep 17 00:00:00 2001 From: Aaron Lampros Date: Wed, 1 Feb 2012 13:11:26 -0500 Subject: [PATCH 03/24] Fixes Uncaught Type Error at Line 371 --- session.js | 9 ++++++--- session.min.js | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/session.js b/session.js index a71d677..a21f321 100644 --- a/session.js +++ b/session.js @@ -370,9 +370,12 @@ var session_fetch = (function(win, doc, nav){ doc.getElementsByTagName("body")[0].appendChild(element); }, package_obj: function (obj){ - obj.version = API_VERSION; - var ret = JSON.stringify(obj); - delete obj.version; return ret; + if(obj) { + obj.version = API_VERSION; + var ret = JSON.stringify(obj); + delete obj.version; + return ret; + } }, get_obj: function(cookie_name){ var obj; diff --git a/session.min.js b/session.min.js index e622331..6bed9ac 100644 --- a/session.min.js +++ b/session.min.js @@ -5,4 +5,4 @@ * Portions of session.js are inspired or borrowed from Underscore.js, and quirksmode.org demo javascript. * This version uses google's jsapi library for location services. * For details, see: https://github.com/codejoust/session.js - */var session_fetch=function(a,b,c){var d=.4,e={use_html5_location:!1,ipinfodb_key:!1,gapi_location:!0,location_cookie:"location",location_cookie_timeout:5,session_timeout:32,session_cookie:"first_session"},f=function(){String.prototype.contains=function(a){if(typeof a=="string")return this.indexOf(a)!==-1;for(var b=0;b1)for(k=0;k1)for(k=0;k Date: Tue, 24 Apr 2012 12:42:11 -0700 Subject: [PATCH 04/24] Update session.js --- session.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/session.js b/session.js index a21f321..737e397 100644 --- a/session.js +++ b/session.js @@ -155,8 +155,8 @@ var session_fetch = (function(win, doc, nav){ { string: nav.platform, subString: "Mac", identity: "Mac" }, { string: nav.userAgent, subString: "iPhone", identity: "iPhone/iPod" }, { string: nav.userAgent, subString: "iPad", identity: "iPad" }, - { string: nav.platform, subString: "Linux", identity: "Linux" }, - { string: nav.userAgent, subString: "Android", identity: "Android" } + { string: nav.userAgent, subString: "Android", identity: "Android" }, + { string: nav.platform, subString: "Linux", identity: "Linux" } ]} }; From d5abb9902da4dbd22eb503a9fae2d481dc4ec3eb Mon Sep 17 00:00:00 2001 From: Iain Nash Date: Fri, 4 May 2012 17:41:45 -0400 Subject: [PATCH 05/24] long-needed updates --- README.md | 2 +- debug.html | 177 ++++++++++++++++++++++++++++++++++++ session.js | 3 +- session.min.js | 2 +- test/spec/extension-spec.js | 39 ++++---- 5 files changed, 202 insertions(+), 21 deletions(-) create mode 100644 debug.html diff --git a/README.md b/README.md index 021b0e2..5408329 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Quick Example: if (session.first_session.visits > 1){ alert('Hi again from ' + session.location.address.city); } else { - if (session.current_session.referrer_info.host.contains('facebook')){ + if (session.contains(session.current_session.referrer_info.host, 'facebook')){ alert('Hi there from '+ session.location.address.city +'. How about liking us on facebook?'); } else if (session.current_session.search.engine){ alert('Did you find what you were looking for from ' + session.current_session.search.engine + '?'); diff --git a/debug.html b/debug.html new file mode 100644 index 0000000..b295e9a --- /dev/null +++ b/debug.html @@ -0,0 +1,177 @@ + + + + Demo for Session.js + + + + + + +

Session.js Debug / Testing Page

+

Script Output:

+
+    loading...
+  
+ + + + + +

+  
+  
+  

Session.JS on GitHub by Iain

+ + + diff --git a/session.js b/session.js index 737e397..707bf67 100644 --- a/session.js +++ b/session.js @@ -34,9 +34,10 @@ var session_fetch = (function(win, doc, nav){ // Session object var SessionRunner = function(){ + win.session = {}; // Helper for querying. // Usage: session.current_session.referrer_info.hostname.contains(['github.com','news.ycombinator.com']) - String.prototype.contains = function(other_str){ + win.session.contains = function(other_str){ if (typeof(other_str) === 'string'){ return (this.indexOf(other_str) !== -1); } for (var i = 0; i < other_str.length; i++){ diff --git a/session.min.js b/session.min.js index 6bed9ac..dfad560 100644 --- a/session.min.js +++ b/session.min.js @@ -5,4 +5,4 @@ * Portions of session.js are inspired or borrowed from Underscore.js, and quirksmode.org demo javascript. * This version uses google's jsapi library for location services. * For details, see: https://github.com/codejoust/session.js - */var session_fetch=function(a,b,c){var d=.4,e={use_html5_location:!1,ipinfodb_key:!1,gapi_location:!0,location_cookie:"location",location_cookie_timeout:5,session_timeout:32,session_cookie:"first_session"},f=function(){String.prototype.contains=function(a){if(typeof a=="string")return this.indexOf(a)!==-1;for(var b=0;b1)for(k=0;k1)for(k=0;k Date: Mon, 11 Jun 2012 18:23:31 -0400 Subject: [PATCH 06/24] Fixed 'start' callback bug. --- session.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/session.js b/session.js index 707bf67..9dc7aad 100644 --- a/session.js +++ b/session.js @@ -34,7 +34,7 @@ var session_fetch = (function(win, doc, nav){ // Session object var SessionRunner = function(){ - win.session = {}; + win.session = win.session || {}; // Helper for querying. // Usage: session.current_session.referrer_info.hostname.contains(['github.com','news.ycombinator.com']) win.session.contains = function(other_str){ From 9545b1b9a3a96c566fd5142c9d1414125d06fbd6 Mon Sep 17 00:00:00 2001 From: Iain Nash Date: Sun, 17 Jun 2012 09:12:30 -0400 Subject: [PATCH 07/24] Adding license file and updating packed version --- session.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/session.min.js b/session.min.js index dfad560..d008d80 100644 --- a/session.min.js +++ b/session.min.js @@ -5,4 +5,4 @@ * Portions of session.js are inspired or borrowed from Underscore.js, and quirksmode.org demo javascript. * This version uses google's jsapi library for location services. * For details, see: https://github.com/codejoust/session.js - */var session_fetch=function(a,b,c){var d=.4,e={use_html5_location:!1,ipinfodb_key:!1,gapi_location:!0,location_cookie:"location",location_cookie_timeout:5,session_timeout:32,session_cookie:"first_session"},f=function(){a.session={},a.session.contains=function(a){if(typeof a=="string")return this.indexOf(a)!==-1;for(var b=0;b1)for(k=0;k1)for(k=0;k Date: Thu, 9 Aug 2012 14:20:01 -0700 Subject: [PATCH 08/24] Fixing viewport for ie --- LICENSE | 6 ++++++ session.js | 4 ++-- session.min.js | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3080ecd --- /dev/null +++ b/LICENSE @@ -0,0 +1,6 @@ +session.js 0.4.1 +(c) 2012 Iain, CodeJoust +session.js is freely distributable under the MIT license. +Portions of session.js are inspired or borrowed from Underscore.js, and quirksmode.org demo javascript. +This version uses google's jsapi library for location services. +For details, see: https://github.com/codejoust/session.js diff --git a/session.js b/session.js index 9dc7aad..190654b 100644 --- a/session.js +++ b/session.js @@ -194,8 +194,8 @@ var session_fetch = (function(win, doc, nav){ } }; device.viewport = { - width: win.innerWidth || doc.body.clientWidth || doc.documentElement.clientWidth, - height: win.innerHeight || doc.body.clientHeight || doc.documentElement.clientHeight + width: win.innerWidth || doc.documentElement.clientWidth || doc.body.clientWidth, + height: win.innerHeight || doc.documentElement.clientHeight || doc.body.clientHeight }; device.is_tablet = !!nav.userAgent.match(/(iPad|SCH-I800|xoom|kindle)/i); device.is_phone = !device.is_tablet && !!nav.userAgent.match(/(iPhone|iPod|blackberry|android 0.5|htc|lg|midp|mmp|mobile|nokia|opera mini|palm|pocket|psp|sgh|smartphone|symbian|treo mini|Playstation Portable|SonyEricsson|Samsung|MobileExplorer|PalmSource|Benq|Windows Phone|Windows Mobile|IEMobile|Windows CE|Nintendo Wii)/i); diff --git a/session.min.js b/session.min.js index d008d80..3ab6e9b 100644 --- a/session.min.js +++ b/session.min.js @@ -5,4 +5,4 @@ * Portions of session.js are inspired or borrowed from Underscore.js, and quirksmode.org demo javascript. * This version uses google's jsapi library for location services. * For details, see: https://github.com/codejoust/session.js - */var session_fetch=function(a,b,c){var d=.4,e={use_html5_location:!1,ipinfodb_key:!1,gapi_location:!0,location_cookie:"location",location_cookie_timeout:5,session_timeout:32,session_cookie:"first_session"},f=function(){a.session=a.session||{},a.session.contains=function(a){if(typeof a=="string")return this.indexOf(a)!==-1;for(var b=0;b1)for(k=0;k1)for(l=0;l Date: Wed, 31 Oct 2012 15:48:18 -0300 Subject: [PATCH 09/24] Call ipinfodb only when the cookie expires MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, session.js would call the ipinfodb service on every user's request and reset the cookie, even if the cookie was already present. Now ipinfodb will only set the user location if the cookie doesn't already exist.  --- session.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/session.js b/session.js index 190654b..89b6369 100644 --- a/session.js +++ b/session.js @@ -307,7 +307,7 @@ var session_fetch = (function(win, doc, nav){ ipinfodb_location: function(api_key){ return function (callback){ var location_cookie = util.get_obj(options.location_cookie); - if (location_cookie && location_cookie.source === 'ipinfodb'){ callback(location_cookie); } + if (!location_cookie && location_cookie.source === 'ipinfodb'){ win.ipinfocb = function(data){ if (data.statusCode === "OK"){ data.source = "ipinfodb"; @@ -321,6 +321,7 @@ var session_fetch = (function(win, doc, nav){ else { callback({error: true, source: "ipinfodb", message: data.statusMessage}); } }} util.embed_script("http://api.ipinfodb.com/v3/ip-city/?key=" + api_key + "&format=json&callback=ipinfocb"); + } else { callback(location_cookie); } }} }; From 0cc51d103d22517dc940ffb49f886f35d99d5e14 Mon Sep 17 00:00:00 2001 From: Victor Homyakov Date: Fri, 3 May 2013 12:59:04 +0300 Subject: [PATCH 10/24] Fixed jshint warnings (global vars, missing or extra semicolons) --- session.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/session.js b/session.js index 190654b..8a35c99 100644 --- a/session.js +++ b/session.js @@ -42,10 +42,10 @@ var session_fetch = (function(win, doc, nav){ return (this.indexOf(other_str) !== -1); } for (var i = 0; i < other_str.length; i++){ if (this.indexOf(other_str[i]) !== -1){ return true; } } - return false; } + return false; }; // Merge options if (win.session && win.session.options) { - for (option in win.session.options){ + for (var option in win.session.options){ options[option] = win.session.options[option]; } } // Modules to run @@ -213,7 +213,7 @@ var session_fetch = (function(win, doc, nav){ } } return false; } return false; - } + }; return { flash: check_plugin("flash"), silverlight: check_plugin("silverlight"), @@ -298,11 +298,11 @@ var session_fetch = (function(win, doc, nav){ options.location_cookie, util.package_obj(win.google.loader.ClientLocation), options.location_cookie_timeout * 60 * 60 * 1000); - }} + }}; util.embed_script("https://www.google.com/jsapi?callback=gloader_ready"); } else { callback(location); - }} + }}; }, ipinfodb_location: function(api_key){ return function (callback){ @@ -319,7 +319,7 @@ var session_fetch = (function(win, doc, nav){ } else { if (options.gapi_location){ return modules.gapi_location()(callback); } else { callback({error: true, source: "ipinfodb", message: data.statusMessage}); } - }} + }}; util.embed_script("http://api.ipinfodb.com/v3/ip-city/?key=" + api_key + "&format=json&callback=ipinfocb"); }} }; @@ -328,7 +328,7 @@ var session_fetch = (function(win, doc, nav){ var util = { parse_url: function(url_str){ var a = doc.createElement("a"), query = {}; - a.href = url_str; query_str = a.search.substr(1); + a.href = url_str; var query_str = a.search.substr(1); // Disassemble query string if (query_str != ''){ var pairs = query_str.split("&"), i = 0, @@ -349,7 +349,7 @@ var session_fetch = (function(win, doc, nav){ }, set_cookie: function(cname, value, expires, options){ // from jquery.cookie.js if (!cname){ return null; } - if (!options){ var options = {}; } + if (!options){ options = {}; } if (value === null || value === undefined){ expires = -1; } if (expires){ options.expires = (new Date().getTime()) + expires; } return (doc.cookie = [ @@ -380,7 +380,7 @@ var session_fetch = (function(win, doc, nav){ }, get_obj: function(cookie_name){ var obj; - try { obj = JSON.parse(util.get_cookie(cookie_name)); } catch(e){}; + try { obj = JSON.parse(util.get_cookie(cookie_name)); } catch(e){} if (obj && obj.version == API_VERSION){ delete obj.version; return obj; } From fb655a882ee447f2ad14f43e019b50e0bd775a35 Mon Sep 17 00:00:00 2001 From: _pants <_pants@getlantern.org> Date: Mon, 3 Jun 2013 15:56:06 -0400 Subject: [PATCH 11/24] add missing "var" found with "use strict" --- session.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/session.js b/session.js index 190654b..70f1bad 100644 --- a/session.js +++ b/session.js @@ -7,6 +7,7 @@ * For details, see: https://github.com/codejoust/session.js */ var session_fetch = (function(win, doc, nav){ + 'use strict'; // Changing the API Version invalidates olde cookies with previous api version tags. var API_VERSION = 0.4; // Settings: defaults @@ -328,7 +329,7 @@ var session_fetch = (function(win, doc, nav){ var util = { parse_url: function(url_str){ var a = doc.createElement("a"), query = {}; - a.href = url_str; query_str = a.search.substr(1); + a.href = url_str; var query_str = a.search.substr(1); // Disassemble query string if (query_str != ''){ var pairs = query_str.split("&"), i = 0, From 08ac4df66636cc1a77c39fed1a9b0fe20e738c32 Mon Sep 17 00:00:00 2001 From: Iain Nash Date: Mon, 2 Dec 2013 08:49:16 -0800 Subject: [PATCH 12/24] Session updates for os and cookie changes --- session.js | 60 ++++++++++++++++++++++++++++++++++++++++++-------- session.min.js | 9 +------- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/session.js b/session.js index 2ea4629..4a9244a 100644 --- a/session.js +++ b/session.js @@ -30,7 +30,9 @@ var session_fetch = (function(win, doc, nav){ // Session expiration in days session_timeout: 32, // Session cookie name (set blank to disable cookie) - session_cookie: "first_session" + session_cookie: "first_session", + get_object: null, set_object: null // used for cookie session adaptors + // if null, will be reset to use cookies by default. }; // Session object @@ -110,11 +112,22 @@ var session_fetch = (function(win, doc, nav){ // Browser (and OS) detection var browser = { detect: function(){ - return { + var ret = { browser: this.search(this.data.browser), version: this.search(nav.userAgent) || this.search(nav.appVersion), os: this.search(this.data.os) - } }, + }; + if (ret.os=='Linux'){ + var distros = ['CentOS','Debian','Fedora','Gentoo','Mandriva','Mageia','Red Hat','Slackware','SUSE','Turbolinux','Ubuntu']; + for (var i = 0; i < distros.length;i++){ + if (nav.useragent.toLowerCase().match(distros[i].toLowerCase())){ + ret.distro = distros[i]; + break; + } + } + } + return ret; + }, search: function(data) { if (typeof data === "object"){ // search for string match @@ -215,8 +228,19 @@ var session_fetch = (function(win, doc, nav){ return false; } return false; }; + var check_activex_flash = function(versions){ + var found = true; + for (var i = 0; i < versions.length; i++){ + try { + var obj = new ActiveXObject("ShockwaveFlash.ShockwaveFlash" + versions[i]) + , found = !0; + } catch (e){ /* nil */ } + if (found) return true; + } + return false; + } return { - flash: check_plugin("flash"), + flash: check_plugin("flash") || check_activex_flash(['.7','.6','']), silverlight: check_plugin("silverlight"), java: check_plugin("java"), quicktime: check_plugin("quicktime") @@ -267,7 +291,7 @@ var session_fetch = (function(win, doc, nav){ session.visits++; session.time_since_last_visit = session.last_visit - session.prev_visit; } - util.set_cookie(cookie, util.package_obj(session), expires); + util.set_obj(cookie, session, expires); return session; }, html5_location: function(){ @@ -295,9 +319,9 @@ var session_fetch = (function(win, doc, nav){ } else { callback({error: true, source: "google"}); } - util.set_cookie( + util.set_obj( options.location_cookie, - util.package_obj(win.google.loader.ClientLocation), + win.google.loader.ClientLocation, options.location_cookie_timeout * 60 * 60 * 1000); }}; util.embed_script("https://www.google.com/jsapi?callback=gloader_ready"); @@ -305,6 +329,15 @@ var session_fetch = (function(win, doc, nav){ callback(location); }}; }, + architecture: function(){ + var arch = n.userAgent.match(/x86_64|Win64|WOW64|x86-64|x64\;|AMD64|amd64/) || + (n.cpuClass === 'x64') ? 'x64' : 'x86'; + return { + arch: arch, + is_x64: arch == 'x64', + is_x86: arch == 'x68' + } + }, ipinfodb_location: function(api_key){ return function (callback){ var location_cookie = util.get_obj(options.location_cookie); @@ -312,9 +345,9 @@ var session_fetch = (function(win, doc, nav){ win.ipinfocb = function(data){ if (data.statusCode === "OK"){ data.source = "ipinfodb"; - util.set_cookie( + util.set_obj( options.location_cookie, - util.package_obj(data), + data, options.location_cookie * 60 * 60 * 1000); callback(data); } else { @@ -380,6 +413,9 @@ var session_fetch = (function(win, doc, nav){ return ret; } }, + set_obj: function(cname, value, expires, options){ + util.set_cookie(cname, util.package_obj(value), expires, options); + }, get_obj: function(cookie_name){ var obj; try { obj = JSON.parse(util.get_cookie(cookie_name)); } catch(e){} @@ -389,6 +425,12 @@ var session_fetch = (function(win, doc, nav){ } }; + // cookie options override + if (options.get_object != null){ + util.get_obj = options['get_object']; } + if (options.set_object != null){ + util.set_obj = options['set_object']; } + // JSON var JSON = { parse: (win.JSON && win.JSON.parse) || function(data){ diff --git a/session.min.js b/session.min.js index 3ab6e9b..85b992c 100644 --- a/session.min.js +++ b/session.min.js @@ -1,8 +1 @@ -/** - * session.js 0.4.1 - * (c) 2012 Iain, CodeJoust - * session.js is freely distributable under the MIT license. - * Portions of session.js are inspired or borrowed from Underscore.js, and quirksmode.org demo javascript. - * This version uses google's jsapi library for location services. - * For details, see: https://github.com/codejoust/session.js - */var session_fetch=function(e,t,n){var r=.4,i={use_html5_location:!1,ipinfodb_key:!1,gapi_location:!0,location_cookie:"location",location_cookie_timeout:5,session_timeout:32,session_cookie:"first_session"},s=function(){e.session=e.session||{},e.session.contains=function(e){if(typeof e=="string")return this.indexOf(e)!==-1;for(var t=0;t1)for(l=0;l1){for(i=0;i Date: Thu, 26 Dec 2013 18:24:17 +0900 Subject: [PATCH 13/24] Fix typo useragent to userAgent --- session.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/session.js b/session.js index 4a9244a..3d343f9 100644 --- a/session.js +++ b/session.js @@ -120,7 +120,7 @@ var session_fetch = (function(win, doc, nav){ if (ret.os=='Linux'){ var distros = ['CentOS','Debian','Fedora','Gentoo','Mandriva','Mageia','Red Hat','Slackware','SUSE','Turbolinux','Ubuntu']; for (var i = 0; i < distros.length;i++){ - if (nav.useragent.toLowerCase().match(distros[i].toLowerCase())){ + if (nav.userAgent.toLowerCase().match(distros[i].toLowerCase())){ ret.distro = distros[i]; break; } From f4a4073587037f31db71ac0f8540730e21edf0a2 Mon Sep 17 00:00:00 2001 From: Kyohei Hamada Date: Fri, 7 Feb 2014 20:19:52 +0900 Subject: [PATCH 14/24] Set width/height to 0 if clientWidth/clientHeight is undefined ex) inside iframe --- session.js | 7 +++++-- test/spec/device-spec.js | 10 ++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/session.js b/session.js index 4a9244a..bdb9292 100644 --- a/session.js +++ b/session.js @@ -207,9 +207,12 @@ var session_fetch = (function(win, doc, nav){ height: win.screen.height } }; + var width, height; + try{ width = win.innerWidth || doc.documentElement.clientWidth || doc.body.clientWidth; } catch(e) { width = 0; } + try{ height = win.innerHeight || doc.documentElement.clientHeight || doc.body.clientHeight; } catch(e) { height = 0; } device.viewport = { - width: win.innerWidth || doc.documentElement.clientWidth || doc.body.clientWidth, - height: win.innerHeight || doc.documentElement.clientHeight || doc.body.clientHeight + width: width, + height: height }; device.is_tablet = !!nav.userAgent.match(/(iPad|SCH-I800|xoom|kindle)/i); device.is_phone = !device.is_tablet && !!nav.userAgent.match(/(iPhone|iPod|blackberry|android 0.5|htc|lg|midp|mmp|mobile|nokia|opera mini|palm|pocket|psp|sgh|smartphone|symbian|treo mini|Playstation Portable|SonyEricsson|Samsung|MobileExplorer|PalmSource|Benq|Windows Phone|Windows Mobile|IEMobile|Windows CE|Nintendo Wii)/i); diff --git a/test/spec/device-spec.js b/test/spec/device-spec.js index e313ae1..8ccd3fe 100644 --- a/test/spec/device-spec.js +++ b/test/spec/device-spec.js @@ -39,6 +39,16 @@ describe('screen size', function(){ expect(mock.win.session.device.viewport.width).toEqual(342) expect(mock.win.session.device.viewport.height).toEqual(434) }) + it('gets 0 size when inside iframe', function(){ + mock.doc.documentElement = {} + mock.doc.documentElement.clientWidth = 0 + mock.doc.documentElement.clientHeight = 0 + mock.doc.body = undefined + mock.run_sess() + expect(mock.win.session.device.viewport).toBeTruthy() + expect(mock.win.session.device.viewport.width).toEqual(0) + expect(mock.win.session.device.viewport.height).toEqual(0) + }) }) describe('mobile / tablet device checks', function(){ From 800021692a74b617a4fd56566ee46beb6d826987 Mon Sep 17 00:00:00 2001 From: Ilya Tsuryev Date: Wed, 23 Jul 2014 17:08:05 +0300 Subject: [PATCH 15/24] FIx IE11 detection, fix tests for IE --- session.js | 1 + test/SpecRunner.html | 1 + test/spec/browser-spec.js | 59 +++++++++++++++++++++++++-------------- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/session.js b/session.js index 55fe89b..db6dedf 100644 --- a/session.js +++ b/session.js @@ -162,6 +162,7 @@ var session_fetch = (function(win, doc, nav){ { string: nav.vendor, subString: "Camino", identity: "Camino" }, { string: nav.userAgent, subString: "Netscape", identity: "Netscape" }, { string: nav.userAgent, subString: "MSIE", identity: "Explorer", versionSearch: "MSIE" }, + { string: nav.userAgent, subString: "Trident", identity: "Explorer", versionSearch: "rv" }, { string: nav.userAgent, subString: "Gecko", identity: "Mozilla", versionSearch: "rv" }, { string: nav.userAgent, subString: "Mozilla", identity: "Netscape", versionSearch: "Mozilla" } ], diff --git a/test/SpecRunner.html b/test/SpecRunner.html index b9e97e4..e722ba6 100644 --- a/test/SpecRunner.html +++ b/test/SpecRunner.html @@ -25,6 +25,7 @@ + diff --git a/test/spec/browser-spec.js b/test/spec/browser-spec.js index b13609b..197147c 100644 --- a/test/spec/browser-spec.js +++ b/test/spec/browser-spec.js @@ -1,25 +1,45 @@ // @todo - can tests be dynamically created in Jasmine for this to work? -/* -var mock = create_mock() +var mock = create_mock(); +var _getTestHandler = function(testData, expectedResult) { + return function() { + mock.nav.userAgent = testData[3]; + mock.nav.appVersion = testData[2]; + mock.nav.platform = testData[1]; + mock.run_sess(); + + var browser_data = mock.win.session.browser; + expect(browser_data.browser).toEqual(expectedResult.browser); + expect(browser_data.version).toEqual(expectedResult.version); + expect(browser_data.os).toEqual(expectedResult.os); + }; +}; describe('IE Browser Names', function(){ var ie_tests = [ - ['mise 9', 'Win', '9.0', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)'], - ['mise 8 .net', 'Win', '8.0', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)'], - ['mise 9', 'Win', '9.0', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)'], - ['mise 8 .net', 'Win', '8.0', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)'], - ['mise 8 .net 2', 'Win', '8.0', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)'] + ['msie 11', 'Win', '11.0', 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv 11.0) like Gecko'], + ['msie 10', 'Win', '10.0', 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)'], + ['msie 9', 'Win', '9.0', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)'], + ['msie 8 .net', 'Win', '8.0', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; .NET4.0E)'], + ['msie 9', 'Win', '9.0', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)'], + ['msie 8 .net', 'Win', '8.0', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)'], + ['msie 8 .net 2', 'Win', '8.0', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)'] + ]; + var ie_tests_expected_result = [ + { browser: 'Explorer', version: 11, os: 'Windows' }, + { browser: 'Explorer', version: 10, os: 'Windows' }, + { browser: 'Explorer', version: 9, os: 'Windows' }, + { browser: 'Explorer', version: 8, os: 'Windows' }, + { browser: 'Explorer', version: 9, os: 'Windows' }, + { browser: 'Explorer', version: 8, os: 'Windows' }, + { browser: 'Explorer', version: 8, os: 'Windows' }, ]; - for (var i = 0; i < ie_tests.length; i++){ + for (var i = 0; i < ie_tests.length; i++) { var ie_test = ie_tests[i]; - it(ie_test[0], function(){ - mock.nav.userAgent = ie_test[3]; - mock.nav.appVersion = ie_test[2]; - mock.run_sess() - }) + var expected_result = ie_tests_expected_result[i]; + it(ie_test[0], _getTestHandler(ie_test, expected_result)); } -}) +}); describe('Firefox Browser Names', function(){ var firefox_tests = [ @@ -28,7 +48,7 @@ describe('Firefox Browser Names', function(){ ['firefox 3.6', '3.6.24', 'Mozilla/5.0 (X11; U; Linux i686; sk; rv:1.9.2.24) Gecko/20111107 Ubuntu/10.04 (lucid) Firefox/3.6.24'], ['firefox beta', '11.0a2', 'Mozilla/5.0 (X11; Linux x86_64; rv:11.0a2) Gecko/20120107 Firefox/11.0a2'] ]; -}) +}); describe('Safari Browser Names', function(){ var safari_tests = [ @@ -38,14 +58,11 @@ describe('Safari Browser Names', function(){ ['5.1 ipad', '5.1', 'Mozilla/5.0 (iPad; CPU OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A405 Safari/7534.48.3'], ['4.1 iphone', '5.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A405 Safari/7534.48.3'] ]; - -}) - +}); describe('Chrome Browser Names', function(){ var chrome_tests = [ - + ]; -}) -*/ \ No newline at end of file +}); From ecea37e6f191882ec6aaef00fb1822a8ca566910 Mon Sep 17 00:00:00 2001 From: Ilya Tsuryev Date: Tue, 26 Aug 2014 11:49:47 +0300 Subject: [PATCH 16/24] Fix document body check --- session.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/session.js b/session.js index 55fe89b..c5c5a1b 100644 --- a/session.js +++ b/session.js @@ -406,7 +406,7 @@ var session_fetch = (function(win, doc, nav){ var element = doc.createElement("script"); element.type = "text/javascript"; element.src = url; - doc.getElementsByTagName("body")[0].appendChild(element); + (doc.body || doc.getElementsByTagName("body")[0] || doc.head).appendChild(element); }, package_obj: function (obj){ if(obj) { From 195d8c510033fc97496bb8552fc350eafe49593e Mon Sep 17 00:00:00 2001 From: Jury Razumau Date: Fri, 7 Aug 2015 17:45:06 +0300 Subject: [PATCH 17/24] Add Microsoft Edge support --- session.js | 1 + test/spec/browser-spec.js | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/session.js b/session.js index 7cb4776..49e63f9 100644 --- a/session.js +++ b/session.js @@ -152,6 +152,7 @@ var session_fetch = (function(win, doc, nav){ }, data: { browser: [ + { string: nav.userAgent, subString: "Edge", identity: "Edge"}, { string: nav.userAgent, subString: "Chrome", identity: "Chrome" }, { string: nav.userAgent, subString: "OmniWeb", versionSearch: "OmniWeb/", identity: "OmniWeb" }, { string: nav.vendor, subString: "Apple", identity: "Safari", versionSearch: "Version" }, diff --git a/test/spec/browser-spec.js b/test/spec/browser-spec.js index 197147c..b4e9d86 100644 --- a/test/spec/browser-spec.js +++ b/test/spec/browser-spec.js @@ -41,6 +41,21 @@ describe('IE Browser Names', function(){ } }); +describe('Edge Browser Names', function (){ + var edge_tests = [ + ['edge', 'Win', '12', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240'] + ]; + var edge_tests_expected_result = [ + { browser: 'Edge', version: 12.1024, os: 'Windows' } + ]; + for (var i = 0; i < edge_tests.length; i++) { + var edge_test = edge_tests[i]; + var expected_result = edge_tests_expected_result[i]; + it(edge_test[0], _getTestHandler(edge_test, expected_result)); + } + +}); + describe('Firefox Browser Names', function(){ var firefox_tests = [ ['firefox 9.0.1', '9.0.1', 'Mozilla/5.0 (Windows NT 5.1; rv:9.0.1) Gecko/20100101 Firefox/9.0.1'], @@ -63,6 +78,15 @@ describe('Safari Browser Names', function(){ describe('Chrome Browser Names', function(){ var chrome_tests = [ - + ['chrome 44', 'Win', '44', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36'], ]; + + var chrome_tests_expected_result = [ + { browser: 'Chrome', version: 44, os: 'Windows' } + ]; + for (var i = 0; i < chrome_tests.length; i++) { + var chrome_test = chrome_tests[i]; + var expected_result = chrome_tests_expected_result[i]; + it(chrome_test[0], _getTestHandler(chrome_test, expected_result)); + } }); From c11e6f4ad588f36d1516131c87eabf7ca37f8aee Mon Sep 17 00:00:00 2001 From: Anfa Abukar Date: Fri, 31 Mar 2017 15:33:06 -0400 Subject: [PATCH 18/24] removed version from android regexp --- session.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/session.js b/session.js index 49e63f9..0fecd79 100644 --- a/session.js +++ b/session.js @@ -217,7 +217,7 @@ var session_fetch = (function(win, doc, nav){ height: height }; device.is_tablet = !!nav.userAgent.match(/(iPad|SCH-I800|xoom|kindle)/i); - device.is_phone = !device.is_tablet && !!nav.userAgent.match(/(iPhone|iPod|blackberry|android 0.5|htc|lg|midp|mmp|mobile|nokia|opera mini|palm|pocket|psp|sgh|smartphone|symbian|treo mini|Playstation Portable|SonyEricsson|Samsung|MobileExplorer|PalmSource|Benq|Windows Phone|Windows Mobile|IEMobile|Windows CE|Nintendo Wii)/i); + device.is_phone = !device.is_tablet && !!nav.userAgent.match(/(iPhone|iPod|blackberry|android|htc|lg|midp|mmp|mobile|nokia|opera mini|palm|pocket|psp|sgh|smartphone|symbian|treo mini|Playstation Portable|SonyEricsson|Samsung|MobileExplorer|PalmSource|Benq|Windows Phone|Windows Mobile|IEMobile|Windows CE|Nintendo Wii)/i); device.is_mobile = device.is_tablet || device.is_phone; return device; }, From 66ba3d7366feee0d353096d4bd1c5063cd828328 Mon Sep 17 00:00:00 2001 From: SandeepJoelFreshdesk Date: Fri, 10 Aug 2018 16:55:21 +0530 Subject: [PATCH 19/24] Add npm package.json --- package.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 0000000..9158349 --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "session.js", + "version": "0.4.1", + "description": "Gives information about the current session.", + "main": "session.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/codejoust/session.js.git" + }, + "keywords": [ + "session" + ], + "author": "codejoust", + "license": "MIT", + "bugs": { + "url": "https://github.com/codejoust/session.js/issues" + }, + "homepage": "https://github.com/codejoust/session.js#readme" +} From f966e9a695ac5c52ed24ab289f9fce838a7a24a8 Mon Sep 17 00:00:00 2001 From: HacKan Date: Wed, 9 Oct 2019 01:48:44 -0300 Subject: [PATCH 20/24] Refactor demo and debug pages Fix missing character encoding and html lang tag. Refactor code structure and missplaced elements. Change script source for session.js to run locally. --- debug.html | 377 +++++++++++++++++++++++++++++++---------------------- demo.html | 345 ++++++++++++++++++++++++++++-------------------- 2 files changed, 422 insertions(+), 300 deletions(-) diff --git a/debug.html b/debug.html index b295e9a..928e9d4 100644 --- a/debug.html +++ b/debug.html @@ -1,177 +1,240 @@ - + - Demo for Session.js - - - + Session.js example usage + + + + -

Session.js Debug / Testing Page

-

Script Output:

-
+

Session.js Debug / Testing Page

+

Script Output:

+
     loading...
   
- - - + + - -

-  
+
+
+

+
-  
-  

Session.JS on GitHub by Iain

+ + +

Session.JS on GitHub by Iain

diff --git a/demo.html b/demo.html index 26c7146..fabe432 100644 --- a/demo.html +++ b/demo.html @@ -1,154 +1,213 @@ - - Demo for Session.js - + + Demo for Session.js + + -

Session.js Demo Page

-

Demo output:

-
+

Session.js Demo Page

+

Demo output:

+
     loading...
   
- -

Session.JS on GitHub by Iain

- +

Session.JS on GitHub by Iain

+ - + + From 09c84bfe6dc9b5d5fe900dd09980f3ce9e48757f Mon Sep 17 00:00:00 2001 From: HacKan Date: Wed, 9 Oct 2019 01:55:18 -0300 Subject: [PATCH 21/24] Refactor session.js Massive refactor to polish the code removing unused bits, changing `var` for `let`, fixing insecure http protocol for https and fixing architecture module that was broken because of a missnamed variable. Rename cookie to a more significative name: `session-js`. --- session.js | 972 +++++++++++++++++++++++++++++------------------------ 1 file changed, 529 insertions(+), 443 deletions(-) diff --git a/session.js b/session.js index 0fecd79..8ee5451 100644 --- a/session.js +++ b/session.js @@ -6,467 +6,553 @@ * This version uses google's jsapi library for location services. * For details, see: https://github.com/codejoust/session.js */ -var session_fetch = (function(win, doc, nav){ - 'use strict'; - // Changing the API Version invalidates olde cookies with previous api version tags. - var API_VERSION = 0.4; - // Settings: defaults - var options = { - // Use the HTML5 Geolocation API - // this ONLY returns lat & long, no city/address - use_html5_location: false, - // Attempts to use IPInfoDB if provided a valid key - // Get a key at http://ipinfodb.com/register.php - ipinfodb_key: false, - // Leaving true allows for fallback for both - // the HTML5 location and the IPInfoDB - gapi_location: true, - // Name of the location cookie (set blank to disable cookie) - // - WARNING: different providers use the same cookie - // - if switching providers, remember to use another cookie or provide checks for old cookies - location_cookie: "location", - // Location cookie expiration in hours - location_cookie_timeout: 5, - // Session expiration in days - session_timeout: 32, - // Session cookie name (set blank to disable cookie) - session_cookie: "first_session", - get_object: null, set_object: null // used for cookie session adaptors - // if null, will be reset to use cookies by default. - }; - - // Session object - var SessionRunner = function(){ - win.session = win.session || {}; - // Helper for querying. - // Usage: session.current_session.referrer_info.hostname.contains(['github.com','news.ycombinator.com']) - win.session.contains = function(other_str){ - if (typeof(other_str) === 'string'){ - return (this.indexOf(other_str) !== -1); } - for (var i = 0; i < other_str.length; i++){ - if (this.indexOf(other_str[i]) !== -1){ return true; } } - return false; }; - // Merge options - if (win.session && win.session.options) { - for (var option in win.session.options){ - options[option] = win.session.options[option]; } - } - // Modules to run - // If the module has arguments, - // it _needs_ to return a callback function. - var unloaded_modules = { - api_version: API_VERSION, - locale: modules.locale(), - current_session: modules.session(), - original_session: modules.session( - options.session_cookie, - options.session_timeout * 24 * 60 * 60 * 1000), - browser: modules.browser(), - plugins: modules.plugins(), - time: modules.time(), - device: modules.device() - }; - // Location switch - if (options.use_html5_location){ - unloaded_modules.location = modules.html5_location(); - } else if (options.ipinfodb_key){ - unloaded_modules.location = modules.ipinfodb_location(options.ipinfodb_key); - } else if (options.gapi_location){ - unloaded_modules.location = modules.gapi_location(); - } - // Cache win.session.start - if (win.session && win.session.start){ - var start = win.session.start; - } - // Set up checking, if all modules are ready - var asynchs = 0, module, result, - check_asynch = function(deinc){ - if (deinc){ asynchs--; } - if (asynchs === 0){ - // Run start calback - if (start){ start(win.session); } - } +let session_fetch = (function (win, doc, nav) { + 'use strict'; + // Changing the API Version invalidates old cookies with previous api version tags. + let API_VERSION = 0.4; + // Settings: defaults + let options = { + // Use the HTML5 Geolocation API + // this ONLY returns lat & long, no city/address + use_html5_location: false, + // Attempts to use IPInfoDB if provided a valid key + // Get a key at https://ipinfodb.com/register.php + ipinfodb_key: false, + // Leaving true allows for fallback for both + // the HTML5 location and the IPInfoDB + gapi_location: true, + // Name of the location cookie (set blank to disable cookie) + // - WARNING: different providers use the same cookie + // - if switching providers, remember to use another cookie or provide checks for old cookies + location_cookie: 'location', + // Location cookie expiration in hours + location_cookie_timeout: 5, + // Session expiration in days + session_timeout: 32, + // Session cookie name (set blank to disable cookie) + session_cookie: 'session-js', + get_object: null, set_object: null, // used for cookie session adaptors + // if null, will be reset to use cookies by default. }; - win.session = {}; - // Run asynchronous methods - for (var name in unloaded_modules){ - module = unloaded_modules[name]; - if (typeof module === "function"){ - try { - module(function(data){ - win.session[name] = data; - check_asynch(true); - }); - asynchs++; - } catch(err){ - if (win.console && typeof(console.log) === "function"){ - console.log(err); check_asynch(true); } - } - } else { - win.session[name] = module; - } } - check_asynch(); - }; - - // Browser (and OS) detection - var browser = { - detect: function(){ - var ret = { - browser: this.search(this.data.browser), - version: this.search(nav.userAgent) || this.search(nav.appVersion), - os: this.search(this.data.os) - }; - if (ret.os=='Linux'){ - var distros = ['CentOS','Debian','Fedora','Gentoo','Mandriva','Mageia','Red Hat','Slackware','SUSE','Turbolinux','Ubuntu']; - for (var i = 0; i < distros.length;i++){ - if (nav.userAgent.toLowerCase().match(distros[i].toLowerCase())){ - ret.distro = distros[i]; - break; - } - } - } - return ret; - }, - search: function(data) { - if (typeof data === "object"){ - // search for string match - for(var i = 0; i < data.length; i++) { - var dataString = data[i].string, - dataProp = data[i].prop; - this.version_string = data[i].versionSearch || data[i].identity; - if (dataString){ - if (dataString.indexOf(data[i].subString) != -1){ - return data[i].identity; + // Session object + let SessionRunner = function () { + win.session = win.session || {}; + // Helper for querying. + // Usage: session.current_session.referrer_info.hostname.contains(['github.com','news.ycombinator.com']) + win.session.contains = function (other_str) { + if (typeof (other_str) === 'string') { + return (this.indexOf(other_str) !== -1); + } + for (let i = 0; i < other_str.length; i++) { + if (this.indexOf(other_str[i]) !== -1) { + return true; + } + } + return false; + }; + // Merge options + if (win.session && win.session.options) { + for (let option in win.session.options) { + options[option] = win.session.options[option]; } - } else if (dataProp){ - return data[i].identity; - } } - } else { - // search for version number - var index = data.indexOf(this.version_string); - if (index == -1) return; - return parseFloat(data.substr(index + this.version_string.length + 1)); - } - }, - data: { - browser: [ - { string: nav.userAgent, subString: "Edge", identity: "Edge"}, - { string: nav.userAgent, subString: "Chrome", identity: "Chrome" }, - { string: nav.userAgent, subString: "OmniWeb", versionSearch: "OmniWeb/", identity: "OmniWeb" }, - { string: nav.vendor, subString: "Apple", identity: "Safari", versionSearch: "Version" }, - { prop: win.opera, identity: "Opera", versionSearch: "Version" }, - { string: nav.vendor, subString: "iCab",identity: "iCab" }, - { string: nav.vendor, subString: "KDE", identity: "Konqueror" }, - { string: nav.userAgent, subString: "Firefox", identity: "Firefox" }, - { string: nav.vendor, subString: "Camino", identity: "Camino" }, - { string: nav.userAgent, subString: "Netscape", identity: "Netscape" }, - { string: nav.userAgent, subString: "MSIE", identity: "Explorer", versionSearch: "MSIE" }, - { string: nav.userAgent, subString: "Trident", identity: "Explorer", versionSearch: "rv" }, - { string: nav.userAgent, subString: "Gecko", identity: "Mozilla", versionSearch: "rv" }, - { string: nav.userAgent, subString: "Mozilla", identity: "Netscape", versionSearch: "Mozilla" } - ], - os: [ - { string: nav.platform, subString: "Win", identity: "Windows" }, - { string: nav.platform, subString: "Mac", identity: "Mac" }, - { string: nav.userAgent, subString: "iPhone", identity: "iPhone/iPod" }, - { string: nav.userAgent, subString: "iPad", identity: "iPad" }, - { string: nav.userAgent, subString: "Android", identity: "Android" }, - { string: nav.platform, subString: "Linux", identity: "Linux" } - ]} - }; - - var modules = { - browser: function(){ - return browser.detect(); - }, - time: function(){ - // split date and grab timezone estimation. - // timezone estimation: http://www.onlineaspect.com/2007/06/08/auto-detect-a-time-zone-with-javascript/ - var d1 = new Date(), d2 = new Date(); - d1.setMonth(0); d1.setDate(1); d2.setMonth(6); d2.setDate(1); - return({tz_offset: -(new Date().getTimezoneOffset()) / 60, observes_dst: (d1.getTimezoneOffset() !== d2.getTimezoneOffset()) }); - // Gives a browser estimation, not guaranteed to be correct. - }, - locale: function() { - var lang = (( - nav.language || - nav.browserLanguage || - nav.systemLanguage || - nav.userLanguage - ) || '').split("-"); - if (lang.length == 2){ - return { country: lang[1].toLowerCase(), lang: lang[0].toLowerCase() }; - } else if (lang) { - return {lang: lang[0].toLowerCase(), country: null }; - } else { return{lang: null, country: null }; } - }, - device: function() { - var device = { - screen: { - width: win.screen.width, - height: win.screen.height + // Modules to run + // If the module has arguments, + // it _needs_ to return a callback function. + let unloaded_modules = { + api_version: API_VERSION, + locale: modules.locale(), + current_session: modules.session( + null, + null, + ), + original_session: modules.session( + options.session_cookie, + options.session_timeout * 24 * 60 * 60 * 1000, + ), + browser: modules.browser(), + plugins: modules.plugins(), + time: modules.time(), + device: modules.device(), + architecture: modules.architecture(), + }; + // Location switch + if (options.use_html5_location) { + unloaded_modules.location = modules.html5_location(); + } else if (options.ipinfodb_key) { + unloaded_modules.location = modules.ipinfodb_location(options.ipinfodb_key); + } else if (options.gapi_location) { + unloaded_modules.location = modules.gapi_location(); } - }; - var width, height; - try{ width = win.innerWidth || doc.documentElement.clientWidth || doc.body.clientWidth; } catch(e) { width = 0; } - try{ height = win.innerHeight || doc.documentElement.clientHeight || doc.body.clientHeight; } catch(e) { height = 0; } - device.viewport = { - width: width, - height: height - }; - device.is_tablet = !!nav.userAgent.match(/(iPad|SCH-I800|xoom|kindle)/i); - device.is_phone = !device.is_tablet && !!nav.userAgent.match(/(iPhone|iPod|blackberry|android|htc|lg|midp|mmp|mobile|nokia|opera mini|palm|pocket|psp|sgh|smartphone|symbian|treo mini|Playstation Portable|SonyEricsson|Samsung|MobileExplorer|PalmSource|Benq|Windows Phone|Windows Mobile|IEMobile|Windows CE|Nintendo Wii)/i); - device.is_mobile = device.is_tablet || device.is_phone; - return device; - }, - plugins: function(){ - var check_plugin = function(name){ - if (nav.plugins){ - var plugin, i = 0, length = nav.plugins.length; - for (; i < length; i++ ){ - plugin = nav.plugins[i]; - if (plugin && plugin.name && plugin.name.toLowerCase().indexOf(name) !== -1){ - return true; - } } - return false; - } return false; - }; - var check_activex_flash = function(versions){ - var found = true; - for (var i = 0; i < versions.length; i++){ - try { - var obj = new ActiveXObject("ShockwaveFlash.ShockwaveFlash" + versions[i]) - , found = !0; - } catch (e){ /* nil */ } - if (found) return true; + // Cache win.session.start + let start; + if (win.session && win.session.start) { + start = win.session.start; } - return false; - } - return { - flash: check_plugin("flash") || check_activex_flash(['.7','.6','']), - silverlight: check_plugin("silverlight"), - java: check_plugin("java"), - quicktime: check_plugin("quicktime") - }; - }, - session: function (cookie, expires){ - var session = util.get_obj(cookie); - if (session == null){ - session = { - visits: 1, - start: new Date().getTime(), last_visit: new Date().getTime(), - url: win.location.href, path: win.location.pathname, - referrer: doc.referrer, referrer_info: util.parse_url(doc.referrer), - search: { engine: null, query: null } + // Set up checking, if all modules are ready + let asynchs = 0; + let module; + let check_asynch = function (deinc) { + if (deinc) { + asynchs--; + } + if (asynchs === 0) { + // Run start calback + if (start) { + start(win.session); + } + } }; - var search_engines = [ - { name: "Google", host: "google", query: "q" }, - { name: "Bing", host: "bing.com", query: "q" }, - { name: "Yahoo", host: "search.yahoo", query: "p" }, - { name: "AOL", host: "search.aol", query: "q" }, - { name: "Ask", host: "ask.com", query: "q" }, - { name: "Baidu", host: "baidu.com", query: "wd" } - ], length = search_engines.length, - engine, match, i = 0, - fallbacks = 'q query term p wd query text'.split(' '); - for (i = 0; i < length; i++){ - engine = search_engines[i]; - if (session.referrer_info.host.indexOf(engine.host) !== -1){ - session.search.engine = engine.name; - session.search.query = session.referrer_info.query[engine.query]; - session.search.terms = session.search.query ? session.search.query.split(" ") : null; - break; - } + win.session = {}; + // Run asynchronous methods + for (let name in unloaded_modules) { + module = unloaded_modules[name]; + if (typeof module === 'function') { + try { + module(function (data) { + win.session[name] = data; + check_asynch(true); + }); + asynchs++; + } catch (err) { + if (win.console && typeof (console.log) === 'function') { + console.log(err); + check_asynch(true); + } + } + } else { + win.session[name] = module; + } } - if (session.search.engine === null && session.referrer_info.search.length > 1){ - for (i = 0; i < fallbacks.length; i++){ - var terms = session.referrer_info.query[fallbacks[i]]; - if (terms){ - session.search.engine = "Unknown"; - session.search.query = terms; session.search.terms = terms.split(" "); - break; + check_asynch(); + }; + + + // Browser (and OS) detection + // noinspection JSUnresolvedVariable + let browser = { + detect: function () { + let ret = { + browser: this.search(this.data.browser), + version: this.search(nav.userAgent) || this.search(nav.appVersion), + os: this.search(this.data.os) + }; + if (ret.os === 'Linux') { + let distros = ['CentOS', 'Debian', 'Fedora', 'Gentoo', 'Mandriva', 'Mageia', 'Red Hat', 'Slackware', 'SUSE', 'Turbolinux', 'Ubuntu']; + for (let i = 0; i < distros.length; i++) { + if (nav.userAgent.toLowerCase().match(distros[i].toLowerCase())) { + ret.distro = distros[i]; + break; + } + } + } + return ret; + }, + search: function (data) { + if (typeof data === 'object') { + // search for string match + for (let i = 0; i < data.length; i++) { + let dataString = data[i].string, + dataProp = data[i].prop; + this.version_string = data[i].versionSearch || data[i].identity; + if (dataString) { + if (dataString.indexOf(data[i].subString) !== -1) { + return data[i].identity; + } + } else if (dataProp) { + return data[i].identity; + } + } + } else { + // search for version number + let index = data.indexOf(this.version_string); + if (index === -1) return; + return parseFloat(data.substr(index + this.version_string.length + 1)); } - } + }, + data: { + browser: [ + {string: nav.userAgent, subString: 'Edge', identity: 'Edge'}, + {string: nav.userAgent, subString: 'Chrome', identity: 'Chrome'}, + {string: nav.userAgent, subString: 'OmniWeb', versionSearch: 'OmniWeb/', identity: 'OmniWeb'}, + {string: nav.vendor, subString: 'Apple', identity: 'Safari', versionSearch: 'Version'}, + {prop: win.opera, identity: 'Opera', versionSearch: 'Version'}, + {string: nav.vendor, subString: 'iCab', identity: 'iCab'}, + {string: nav.vendor, subString: 'KDE', identity: 'Konqueror'}, + {string: nav.userAgent, subString: 'Firefox', identity: 'Firefox'}, + {string: nav.vendor, subString: 'Camino', identity: 'Camino'}, + {string: nav.userAgent, subString: 'Netscape', identity: 'Netscape'}, + {string: nav.userAgent, subString: 'MSIE', identity: 'Explorer', versionSearch: 'MSIE'}, + {string: nav.userAgent, subString: 'Trident', identity: 'Explorer', versionSearch: 'rv'}, + {string: nav.userAgent, subString: 'Gecko', identity: 'Mozilla', versionSearch: 'rv'}, + {string: nav.userAgent, subString: 'Mozilla', identity: 'Netscape', versionSearch: 'Mozilla'}, + ], + os: [ + {string: nav.platform, subString: 'Win', identity: 'Windows'}, + {string: nav.platform, subString: 'Mac', identity: 'Mac'}, + {string: nav.userAgent, subString: 'iPhone', identity: 'iPhone/iPod'}, + {string: nav.userAgent, subString: 'iPad', identity: 'iPad'}, + {string: nav.userAgent, subString: 'Android', identity: 'Android'}, + {string: nav.platform, subString: 'Linux', identity: 'Linux'}, + ] } - } else { - session.prev_visit = session.last_visit; - session.last_visit = new Date().getTime(); - session.visits++; - session.time_since_last_visit = session.last_visit - session.prev_visit; - } - util.set_obj(cookie, session, expires); - return session; - }, - html5_location: function(){ - return function(callback){ - nav.geolocation.getCurrentPosition(function(pos){ - pos.source = 'html5'; - callback(pos); - }, function(err) { - if (options.gapi_location){ - modules.gapi_location()(callback); - } else { - callback({error: true, source: 'html5'}); } - }); - }; - }, - gapi_location: function(){ - return function(callback){ - var location = util.get_obj(options.location_cookie); - if (!location || location.source !== 'google'){ - win.gloader_ready = function() { - if ("google" in win){ - if (win.google.loader.ClientLocation){ - win.google.loader.ClientLocation.source = "google"; - callback(win.google.loader.ClientLocation); - } else { - callback({error: true, source: "google"}); - } - util.set_obj( - options.location_cookie, - win.google.loader.ClientLocation, - options.location_cookie_timeout * 60 * 60 * 1000); - }}; - util.embed_script("https://www.google.com/jsapi?callback=gloader_ready"); - } else { - callback(location); - }}; - }, - architecture: function(){ - var arch = n.userAgent.match(/x86_64|Win64|WOW64|x86-64|x64\;|AMD64|amd64/) || - (n.cpuClass === 'x64') ? 'x64' : 'x86'; - return { - arch: arch, - is_x64: arch == 'x64', - is_x86: arch == 'x68' - } - }, - ipinfodb_location: function(api_key){ - return function (callback){ - var location_cookie = util.get_obj(options.location_cookie); - if (!location_cookie && location_cookie.source === 'ipinfodb'){ - win.ipinfocb = function(data){ - if (data.statusCode === "OK"){ - data.source = "ipinfodb"; - util.set_obj( - options.location_cookie, - data, - options.location_cookie * 60 * 60 * 1000); - callback(data); - } else { - if (options.gapi_location){ return modules.gapi_location()(callback); } - else { callback({error: true, source: "ipinfodb", message: data.statusMessage}); } - }}; - util.embed_script("http://api.ipinfodb.com/v3/ip-city/?key=" + api_key + "&format=json&callback=ipinfocb"); - } else { callback(location_cookie); } - }} - }; + }; - // Utilities - var util = { - parse_url: function(url_str){ - var a = doc.createElement("a"), query = {}; - a.href = url_str; var query_str = a.search.substr(1); - // Disassemble query string - if (query_str != ''){ - var pairs = query_str.split("&"), i = 0, - length = pairs.length, parts; - for (; i < length; i++){ - parts = pairs[i].split("="); - if (parts.length === 2){ - query[parts[0]] = decodeURI(parts[1]); } + let modules = { + browser: function () { + return browser.detect(); + }, + time: function () { + // split date and grab timezone estimation. + // timezone estimation: https://www.onlineaspect.com/2007/06/08/auto-detect-a-time-zone-with-javascript/ + let d1 = new Date(), d2 = new Date(); + d1.setMonth(0); + d1.setDate(1); + d2.setMonth(6); + d2.setDate(1); + return ({ + tz_offset: -(new Date().getTimezoneOffset()) / 60, + observes_dst: (d1.getTimezoneOffset() !== d2.getTimezoneOffset()) + }); + // Gives a browser estimation, not guaranteed to be correct. + }, + locale: function () { + let lang = (( + nav.language || + (nav.hasOwnProperty('browserLanguage') + ? nav.browserLanguage + : nav.systemLanguage) + ) || '').split('-'); + if (lang.length === 2) { + return {country: lang[1].toLowerCase(), lang: lang[0].toLowerCase()}; + } else if (lang) { + return {lang: lang[0].toLowerCase(), country: null}; + } else { + return {lang: null, country: null}; + } + }, + device: function () { + let device = { + screen: { + width: win.screen.width, + height: win.screen.height + } + }; + let width, height; + try { + width = win.innerWidth || doc.documentElement.clientWidth || doc.body.clientWidth; + } catch (e) { + width = 0; + } + try { + height = win.innerHeight || doc.documentElement.clientHeight || doc.body.clientHeight; + } catch (e) { + height = 0; + } + device.viewport = { + width: width, + height: height + }; + device.is_tablet = !!nav.userAgent.match(/(iPad|SCH-I800|xoom|kindle)/i); + device.is_phone = !device.is_tablet && !!nav.userAgent.match(/(iPhone|iPod|blackberry|android|htc|lg|midp|mmp|mobile|nokia|opera mini|palm|pocket|psp|sgh|smartphone|symbian|treo mini|Playstation Portable|SonyEricsson|Samsung|MobileExplorer|PalmSource|Benq|Windows Phone|Windows Mobile|IEMobile|Windows CE|Nintendo Wii)/i); + device.is_mobile = device.is_tablet || device.is_phone; + return device; + }, + plugins: function () { + let check_plugin = function (name) { + if (nav.plugins) { + let plugin, i = 0, length = nav.plugins.length; + for (; i < length; i++) { + plugin = nav.plugins[i]; + if (plugin && plugin.name && plugin.name.toLowerCase().indexOf(name) !== -1) { + return true; + } + } + return false; + } + return false; + }; + let check_activex_flash = function (versions) { + let found = false; + for (let i = 0; i < versions.length; i++) { + try { + new ActiveXObject('ShockwaveFlash.ShockwaveFlash' + versions[i]); + found = true; + break; + } catch (e) { /* nil */ + } + } + return found; + }; + return { + flash: check_plugin('flash') || check_activex_flash(['.7', '.6', '']), + silverlight: check_plugin('silverlight'), + java: check_plugin('java'), + quicktime: check_plugin('quicktime') + }; + }, + session: function (cookie, expires) { + let session = util.get_obj(cookie); + if (session == null) { + session = { + visits: 1, + start: new Date().getTime(), last_visit: new Date().getTime(), + url: win.location.href, path: win.location.pathname, + referrer: doc.referrer, referrer_info: util.parse_url(doc.referrer), + search: {engine: null, query: null}, + }; + let search_engines = [ + {name: 'Google', host: 'google', query: 'q'}, + {name: 'Bing', host: 'bing.com', query: 'q'}, + {name: 'Yahoo', host: 'search.yahoo', query: 'p'}, + {name: 'AOL', host: 'search.aol', query: 'q'}, + {name: 'Ask', host: 'ask.com', query: 'q'}, + {name: 'Baidu', host: 'baidu.com', query: 'wd'}, + ]; + let length = search_engines.length; + let engine; + let fallbacks = 'q query term p wd query text'.split(' '); + for (let i = 0; i < length; i++) { + engine = search_engines[i]; + if (session.referrer_info.host.indexOf(engine.host) !== -1) { + session.search.engine = engine.name; + session.search.query = session.referrer_info.query[engine.query]; + session.search.terms = session.search.query ? session.search.query.split(' ') : null; + break; + } + } + if (session.search.engine === null && session.referrer_info.search.length > 1) { + for (let i = 0; i < fallbacks.length; i++) { + let terms = session.referrer_info.query[fallbacks[i]]; + if (terms) { + session.search.engine = 'Unknown'; + session.search.query = terms; + session.search.terms = terms.split(' '); + break; + } + } + } + } else { + session.prev_visit = session.last_visit; + session.last_visit = new Date().getTime(); + session.visits++; + session.time_since_last_visit = session.last_visit - session.prev_visit; + } + util.set_obj(cookie, session, expires); + return session; + }, + html5_location: function () { + return function (callback) { + nav.geolocation.getCurrentPosition(function (pos) { + pos.source = 'html5'; + callback(pos); + }, function (err) { + if (options.gapi_location) { + modules.gapi_location()(callback); + } else { + callback({ + error: true, + source: 'html5', + message: err.message, + }); + } + }); + }; + }, + gapi_location: function () { + return function (callback) { + let location = util.get_obj(options.location_cookie); + if (!location || location.source !== 'google') { + win.gloader_ready = function () { + if ('google' in win + && win.google.hasOwnProperty('loader') + && win.google.loader.hasOwnProperty('ClientLocation') + ) { + if (win.google.loader.ClientLocation) { + win.google.loader.ClientLocation.source = 'google'; + callback(win.google.loader.ClientLocation); + } else { + callback({error: true, source: 'google'}); + } + // noinspection JSUnresolvedVariable + util.set_obj( + options.location_cookie, + win.google.loader.ClientLocation, + options.location_cookie_timeout * 60 * 60 * 1000, + ); + } + }; + util.embed_script('https://www.google.com/jsapi?callback=gloader_ready'); + } else { + callback(location); + } + }; + }, + ipinfodb_location: function (api_key) { + return function (callback) { + let location_cookie = util.get_obj(options.location_cookie); + if (!location_cookie && location_cookie.source === 'ipinfodb') { + win.ipinfocb = function (data) { + if (data.statusCode === 'OK') { + data.source = 'ipinfodb'; + util.set_obj( + options.location_cookie, + data, + options.location_cookie * 60 * 60 * 1000); + callback(data); + } else { + if (options.gapi_location) { + return modules.gapi_location()(callback); + } else { + callback({error: true, source: 'ipinfodb', message: data.statusMessage}); + } + } + }; + util.embed_script('https://api.ipinfodb.com/v3/ip-city/?key=' + api_key + '&format=json&callback=ipinfocb'); + } else { + callback(location_cookie); + } + } + }, + architecture: function () { + let arch = nav.userAgent.match(/x86_64|Win64|WOW64|x86-64|x64;|AMD64|amd64/) || + (nav.hasOwnProperty('cpuClass') && nav.cpuClass === 'x64') ? 'x64' : 'x86'; + return { + arch: arch, + is_x64: arch === 'x64', + is_x86: arch === 'x68', + } + }, + }; + + // Utilities + let util = { + parse_url: function (url_str) { + let a = doc.createElement('a'), query = {}; + a.href = url_str; + let query_str = a.search.substr(1); + // Disassemble query string + if (query_str !== '') { + let pairs = query_str.split('&'), i = 0, + length = pairs.length, parts; + for (; i < length; i++) { + parts = pairs[i].split('='); + if (parts.length === 2) { + query[parts[0]] = decodeURI(parts[1]); + } + } + } + return { + host: a.host, + path: a.pathname, + protocol: a.protocol, + port: a.port === '' ? 80 : a.port, + search: a.search, + query: query + } + }, + set_cookie: function (cname, value, expires, options) { // from jquery.cookie.js + if (!cname) { + return null; + } + if (!options) { + options = {}; + } + if (value === null || value === undefined) { + expires = -1; + } + if (expires) { + options.expires = (new Date().getTime()) + expires; + } + return (doc.cookie = [ + encodeURIComponent(cname), '=', + encodeURIComponent(String(value)), + options.expires ? '; expires=' + new Date(options.expires).toUTCString() : '', // use expires attribute, max-age is not supported by IE + '; path=' + (options.path ? options.path : '/'), + options.domain ? '; domain=' + options.domain : '', + (win.location && win.location.protocol === 'https:') ? '; secure' : '' + ].join('')); + }, + get_cookie: function (cookie_name, result) { // from jquery.cookie.js + return (result = new RegExp('(?:^|; )' + encodeURIComponent(cookie_name) + '=([^;]*)').exec(doc.cookie)) ? decodeURIComponent(result[1]) : null; + }, + embed_script: function (url) { + let element = doc.createElement('script'); + element.type = 'text/javascript'; + element.src = url; + (doc.body || doc.getElementsByTagName('body')[0] || doc.head).appendChild(element); + }, + package_obj: function (obj) { + if (obj) { + obj.version = API_VERSION; + let ret = JSON.stringify(obj); + delete obj.version; + return ret; + } + }, + set_obj: function (cname, value, expires, options) { + util.set_cookie(cname, util.package_obj(value), expires, options); + }, + get_obj: function (cookie_name) { + let obj; + try { + obj = JSON.parse(util.get_cookie(cookie_name)); + } catch (e) { + console.log(e); + } + if (obj && obj.version === API_VERSION) { + delete obj.version; + return obj; + } } - } - return { - host: a.host, - path: a.pathname, - protocol: a.protocol, - port: a.port === '' ? 80 : a.port, - search: a.search, - query: query } - }, - set_cookie: function(cname, value, expires, options){ // from jquery.cookie.js - if (!cname){ return null; } - if (!options){ options = {}; } - if (value === null || value === undefined){ expires = -1; } - if (expires){ options.expires = (new Date().getTime()) + expires; } - return (doc.cookie = [ - encodeURIComponent(cname), '=', - encodeURIComponent(String(value)), - options.expires ? '; expires=' + new Date(options.expires).toUTCString() : '', // use expires attribute, max-age is not supported by IE - '; path=' + (options.path ? options.path : '/'), - options.domain ? '; domain=' + options.domain : '', - (win.location && win.location.protocol === 'https:') ? '; secure' : '' - ].join('')); - }, - get_cookie: function(cookie_name, result){ // from jquery.cookie.js - return (result = new RegExp('(?:^|; )' + encodeURIComponent(cookie_name) + '=([^;]*)').exec(doc.cookie)) ? decodeURIComponent(result[1]) : null; - }, - embed_script: function(url){ - var element = doc.createElement("script"); - element.type = "text/javascript"; - element.src = url; - (doc.body || doc.getElementsByTagName("body")[0] || doc.head).appendChild(element); - }, - package_obj: function (obj){ - if(obj) { - obj.version = API_VERSION; - var ret = JSON.stringify(obj); - delete obj.version; - return ret; - } - }, - set_obj: function(cname, value, expires, options){ - util.set_cookie(cname, util.package_obj(value), expires, options); - }, - get_obj: function(cookie_name){ - var obj; - try { obj = JSON.parse(util.get_cookie(cookie_name)); } catch(e){} - if (obj && obj.version == API_VERSION){ - delete obj.version; return obj; - } - } - }; + }; - // cookie options override - if (options.get_object != null){ - util.get_obj = options['get_object']; } - if (options.set_object != null){ - util.set_obj = options['set_object']; } + // cookie options override + if (options.get_object != null) { + util.get_obj = options['get_object']; + } + if (options.set_object != null) { + util.set_obj = options['set_object']; + } - // JSON - var JSON = { - parse: (win.JSON && win.JSON.parse) || function(data){ - if (typeof data !== "string" || !data){ return null; } - return (new Function("return " + data))(); - }, - stringify: (win.JSON && win.JSON.stringify) || function(object){ - var type = typeof object; - if (type !== "object" || object === null) { - if (type === "string"){ return '"' + object + '"'; } - } else { - var k, v, json = [], - isArray = (object && object.constructor === Array); - for (k in object ) { - v = object[k]; type = typeof v; - if (type === "string") - v = '"' + v + '"'; - else if (type === "object" && v !== null) - v = this.stringify(v); - json.push((isArray ? "" : '"' + k + '":') + v); + // JSON + let JSON = { + parse: (win.hasOwnProperty('JSON') && win.JSON && win.JSON.parse) || function (data) { + if (typeof data !== 'string' || !data) { + return null; + } + return (new Function('return ' + data))(); + }, + stringify: (win.hasOwnProperty('JSON') && win.JSON && win.JSON.stringify) || function (object) { + let type = typeof object; + if (type !== 'object' || object === null) { + if (type === 'string') { + return '"' + object + '"'; + } + } else { + let k, v, json = [], isArray = (object && object.constructor === Array); + for (k in object) { + v = object[k]; + type = typeof v; + if (type === 'string') + v = '"' + v + '"'; + else if (type === 'object' && v !== null) + v = this.stringify(v); + json.push((isArray ? "" : '"' + k + '":') + v); + } + return (isArray ? '[' : '{') + json.join(',') + (isArray ? ']' : '}'); + } } - return (isArray ? "[" : "{") + json.join(",") + (isArray ? "]" : "}"); - } } }; + }; - // Initialize SessionRunner - SessionRunner(); + // Initialize SessionRunner + SessionRunner(); }); // Switch for testing purposes. -if (typeof(window.exports) === 'undefined'){ - session_fetch(window, document, navigator); +if (typeof (window.exports) === 'undefined') { + session_fetch(window, document, navigator); } else { - window.exports.session = session_fetch; + window.exports.session = session_fetch; } From ca6c9c2f6aef7c79acc8002070389c85d35e5933 Mon Sep 17 00:00:00 2001 From: HacKan Date: Wed, 9 Oct 2019 02:01:54 -0300 Subject: [PATCH 22/24] Add a tracker property This property allows to track the session from external libs or a backend. Once set, it will be written to the session and kept in the cookie. --- session.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/session.js b/session.js index 8ee5451..4e27ab2 100644 --- a/session.js +++ b/session.js @@ -33,6 +33,9 @@ let session_fetch = (function (win, doc, nav) { session_cookie: 'session-js', get_object: null, set_object: null, // used for cookie session adaptors // if null, will be reset to use cookies by default. + // Tracker ID: initialize with a random string so that repeated visits are + // easily tracked + tracker_id: null, }; // Session object @@ -66,10 +69,12 @@ let session_fetch = (function (win, doc, nav) { current_session: modules.session( null, null, + options.tracker_id, ), original_session: modules.session( options.session_cookie, options.session_timeout * 24 * 60 * 60 * 1000, + options.tracker_id, ), browser: modules.browser(), plugins: modules.plugins(), @@ -292,10 +297,11 @@ let session_fetch = (function (win, doc, nav) { quicktime: check_plugin('quicktime') }; }, - session: function (cookie, expires) { + session: function (cookie, expires, tracker = null) { let session = util.get_obj(cookie); if (session == null) { session = { + tracker: tracker, visits: 1, start: new Date().getTime(), last_visit: new Date().getTime(), url: win.location.href, path: win.location.pathname, @@ -334,6 +340,10 @@ let session_fetch = (function (win, doc, nav) { } } } else { + // Could've been initialized w/o id, so check and set + if (tracker && !session.tracker) { + session.tracker = tracker; + } session.prev_visit = session.last_visit; session.last_visit = new Date().getTime(); session.visits++; From 640779a0a8e9f684a2c3d408b2a4c2436b06d95b Mon Sep 17 00:00:00 2001 From: HacKan Date: Wed, 9 Oct 2019 02:04:34 -0300 Subject: [PATCH 23/24] Add extra client tracking with on/off switch Create a switch named extra that when set records extra client information. It was added from the demo page. --- session.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/session.js b/session.js index 4e27ab2..2253ca9 100644 --- a/session.js +++ b/session.js @@ -36,6 +36,8 @@ let session_fetch = (function (win, doc, nav) { // Tracker ID: initialize with a random string so that repeated visits are // easily tracked tracker_id: null, + // Set to true to record extra client data + extra: false, }; // Session object @@ -90,6 +92,10 @@ let session_fetch = (function (win, doc, nav) { } else if (options.gapi_location) { unloaded_modules.location = modules.gapi_location(); } + // Extra switch + if (options.extra) { + unloaded_modules.extra = modules.extra_data() + } // Cache win.session.start let start; if (win.session && win.session.start) { @@ -434,6 +440,27 @@ let session_fetch = (function (win, doc, nav) { is_x86: arch === 'x68', } }, + extra_data: function () { + let nav = {}; + for (let obj in navigator) { + if (typeof (navigator[obj]) === 'string') { + nav[obj] = navigator[obj]; + } + } + return { + navigator: nav, + document: { + referrer: document.referrer, + clientWidth: document.documentElement.clientWidth, + clientHeight: document.documentElement.clientHeight, + }, + window: { + innerWidth: window.innerWidth, + innerHeight: window.innerHeight, + location: window.location.href, + }, + } + } }; // Utilities From 7af1e85580660463c4912a7d057bf9fad855a07b Mon Sep 17 00:00:00 2001 From: HacKan Date: Wed, 9 Oct 2019 02:09:13 -0300 Subject: [PATCH 24/24] Add minified script --- session.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/session.min.js b/session.min.js index 85b992c..8899030 100644 --- a/session.min.js +++ b/session.min.js @@ -1 +1 @@ -var session_fetch=function(win,doc,nav){"use strict";var API_VERSION=.4;var options={use_html5_location:false,ipinfodb_key:false,gapi_location:true,location_cookie:"location",location_cookie_timeout:5,session_timeout:32,session_cookie:"first_session",get_object:null,set_object:null};var SessionRunner=function(){win.session=win.session||{};win.session.contains=function(other_str){if(typeof other_str==="string"){return this.indexOf(other_str)!==-1}for(var i=0;i1){for(i=0;i1){for(let i=0;i