From 7440f9e32279f2f441e7aa2d3d221579d5a04840 Mon Sep 17 00:00:00 2001 From: skocheri Date: Fri, 16 Oct 2020 00:21:01 -0700 Subject: [PATCH 1/9] ID Library --- modules/idLibrary.js | 246 ++++++++++++++++++++++++++++ modules/idLibrary.md | 22 +++ test/spec/modules/idLibrary_spec.js | 51 ++++++ 3 files changed, 319 insertions(+) create mode 100644 modules/idLibrary.js create mode 100644 modules/idLibrary.md create mode 100644 test/spec/modules/idLibrary_spec.js diff --git a/modules/idLibrary.js b/modules/idLibrary.js new file mode 100644 index 00000000000..d6aea952432 --- /dev/null +++ b/modules/idLibrary.js @@ -0,0 +1,246 @@ +import {getGlobal} from '../src/prebidGlobal.js'; +import {ajax} from '../src/ajax.js'; +import {config} from '../src/config.js'; +import * as utils from '../src/utils.js'; +import MD5 from 'crypto-js/md5.js'; + +let email; +const LOG_PRE_FIX = 'ID-Library: '; +const CONF_DEFAULT_OBSERVER_DEBOUNCE_MS = 250; +const OBSERVER_CONFIG = { + subtree: true, + attributes: true, + attributeOldValue: false, + childList: true, + attirbuteFilter: ['value'], + characterData: true, + characterDataOldValue: false +}; +const logInfo = createLogInfo(LOG_PRE_FIX); +const logError = createLogError(LOG_PRE_FIX); + +function createLogInfo(prefix) { + return function (...strings) { + utils.logInfo(prefix + ' ', ...strings); + } +} + +function createLogError(prefix) { + return function (...strings) { + utils.logError(prefix + ' ', ...strings); + } +} + +function getEmail(value) { + const matched = value.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi); + if (!matched) { + return null; + } + return matched[0]; +} + +function hasEmail(value) { + const email = getEmail(value); + return !!email; +} + +function bodyAction(conf, mutations, observer) { + logInfo('BODY observer on debounce called'); + + if (email) { + observer.disconnect(); + logInfo('Email is found, body observer disconnected'); + } + + const body = document.body.innerHTML; + + if (hasEmail(body)) { + email = getEmail(body); + + logInfo(`Email obtained from the body ${email}`); + observer.disconnect(); + logInfo('Post data on email found in body'); + postData(conf.url); + } +} + +function targetAction(conf, mutations, observer) { + logInfo('Target observer called'); + + mutations.forEach((mutation) => { + mutation.addedNodes.forEach((node) => { + email = node.textContent; + + if (email) { + logInfo('Email obtained from the target ' + email); + observer.disconnect(); + logInfo(' Post data on email found in target'); + postData(conf.url); + } + }); + }); +} + +function addInputElementsElementListner(conf) { + logInfo('Adding input element listeners'); + const inputs = document.querySelectorAll('input[type=text], input[type=email]'); + inputs.forEach((input) => { + logInfo(` Original Value in Input = ${input.value}`); + input.addEventListener('change', event => processInputChange(event, conf)); + input.addEventListener('blur', event => processInputChange(event, conf)); + }); +} + +function removeInputElementsElementListner(conf) { + logInfo('Removing input element listeners'); + const inputs = document.querySelectorAll('input[type=text], input[type=email]'); + inputs.forEach((input) => { + input.removeEventListener('change', event => processInputChange(event, conf)); + input.removeEventListener('blur', event => processInputChange(event, conf)); + }); +} + +function processInputChange(event, conf) { + const value = event.target.value; + logInfo(`Modified Value of input ${event.target.value}`); + if (hasEmail(value)) { + email = getEmail(value); + + logInfo('Email found in input ' + email); + postData(conf.url); + removeInputElementsElementListner(conf); + } +} + +function debounce(func, wait, immediate) { + let timeout; + + return function (...args) { + const context = this; + const later = function () { + timeout = null; + if (!immediate) { + func.apply(context, args); + } + }; + const callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) { + func.apply(context, args); + } + }; +} + +function handleTargetElement(conf) { + const targetObserver = new MutationObserver(function (mutations, observer) { + logInfo('target observer called'); + debounce(targetAction(conf, mutations, observer), conf.debounce, false); + }); + + const targetElement = document.getElementById(conf.target); + if (targetElement) { + email = targetElement.innerText; + + if (!email) { + logInfo('Finding the email with observer'); + targetObserver.observe(targetElement, OBSERVER_CONFIG); + } else { + logInfo(' Target found with target ' + email); + logInfo(' Post data on email found in target with target'); + postData(conf.url); + } + } +} + +function handleBodyElements(conf) { + if (doesInputElementsHaveEmail()) { + logInfo('Email found in input elements ' + email); + logInfo('Post data on email found in target without'); + postData(conf.url); + return; + } + if (hasEmail(document.body.innerHTML)) { + email = getEmail(document.body.innerHTML); + + logInfo('Email found in body ' + email); + logInfo(' Post data on email found in the body without observer'); + postData(conf.url); + return; + } + addInputElementsElementListner(conf); + const bodyObserver = new MutationObserver(function (mutations, observer) { + logInfo('Body observer called'); + debounce(bodyAction(conf, mutations, observer), conf.debounce, false); + }); + bodyObserver.observe(document.body, OBSERVER_CONFIG); +} + +function doesInputElementsHaveEmail() { + const inputs = document.getElementsByTagName('input'); + + for (let index = 0; index < inputs.length; ++index) { + const curInput = inputs[index]; + + if (hasEmail(curInput.value)) { + email = getEmail(curInput.value); + return true; + } + } + return false; +} + +function syncCallback() { + return { + success: function (responseBody) { + logInfo(' Data synced successfully.'); + }, + error: function () { + logInfo(' Data sync failed.'); + } + } +} + +function postData(url) { + (getGlobal()).refreshUserIds(); + const userIds = (getGlobal()).getUserIds(); + if (!userIds || userIds.length === 0) { + return; + } + logInfo(' Users' + JSON.stringify(userIds)); + const syncPayload = {}; + syncPayload.hid = MD5(email).toString(); + syncPayload.uids = JSON.stringify(userIds); + const payloadString = JSON.stringify(syncPayload); + logInfo(payloadString); + ajax(url, syncCallback(), payloadString, {method: 'POST', withCredentials: true}); +} + +function associateIds(conf) { + if (window.MutationObserver || window.WebKitMutationObserver) { + if (conf.target) { + handleTargetElement(conf); + } else { + handleBodyElements(conf); + } + } +} + +export function setConfig(config) { + if (!config) { + logError('Required confirguration not provided'); + return; + } + if (!config.url) { + logError('The required url is not configured'); + return; + } + if (!config.debounce) { + config.debounce = CONF_DEFAULT_OBSERVER_DEBOUNCE_MS; + logInfo('Set default observer debounce to ' + CONF_DEFAULT_OBSERVER_DEBOUNCE_MS); + } + + associateIds(config); +} + +config.getConfig('idLibrary', config => setConfig(config.idLibrary)); diff --git a/modules/idLibrary.md b/modules/idLibrary.md new file mode 100644 index 00000000000..edd30abfea4 --- /dev/null +++ b/modules/idLibrary.md @@ -0,0 +1,22 @@ +## ID Library Configuration Example + + +|Param |Required |Description | +|----------------|-------------------------------|-----------------------------| +|url |Yes | The url endpoint is used to post the hashed email and user ids. | +|target |No |It should contain the element id from which the email can be read. | +|debounce |No | Time in milliseconds before the email and ids are fetched | + +### Example +``` + pbjs.setConfig({ + idLibrary:{ + url: , + debounce: 250, + target: 'username' + }, + }); +``` + + +``` diff --git a/test/spec/modules/idLibrary_spec.js b/test/spec/modules/idLibrary_spec.js new file mode 100644 index 00000000000..3c55194a85c --- /dev/null +++ b/test/spec/modules/idLibrary_spec.js @@ -0,0 +1,51 @@ +import * as utils from 'src/utils.js'; +import * as idlibrary from 'modules/idLibrary.js'; + +var expect = require('chai').expect; + +describe('currency', function () { + let fakeCurrencyFileServer; + let sandbox; + let clock; + + let fn = sinon.spy(); + + beforeEach(function () { + fakeCurrencyFileServer = sinon.fakeServer.create(); + sinon.stub(utils, 'logInfo'); + sinon.stub(utils, 'logError'); + }); + + afterEach(function () { + utils.logInfo.restore(); + utils.logError.restore(); + fakeCurrencyFileServer.restore(); + idlibrary.setConfig({}); + }); + + describe('setConfig', function () { + beforeEach(function() { + sandbox = sinon.sandbox.create(); + clock = sinon.useFakeTimers(1046952000000); // 2003-03-06T12:00:00Z + }); + + afterEach(function () { + sandbox.restore(); + clock.restore(); + }); + + it('results when no config available', function () { + idlibrary.setConfig({}); + sinon.assert.called(utils.logError); + }); + it('results with config available', function () { + idlibrary.setConfig({ 'url': 'URL' }); + sinon.assert.called(utils.logInfo); + }); + it('results with config default debounce ', function () { + let config = { 'url': 'URL' } + idlibrary.setConfig(config); + expect(config.debounce).to.be.equal(250); + }); + }); +}); From 021cd6985430dc11a896d9cd35a6bcd6c0b691b4 Mon Sep 17 00:00:00 2001 From: skocheri Date: Fri, 16 Oct 2020 10:09:49 -0700 Subject: [PATCH 2/9] build fix --- modules/idLibrary.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/modules/idLibrary.js b/modules/idLibrary.js index d6aea952432..7ce541e1a73 100644 --- a/modules/idLibrary.js +++ b/modules/idLibrary.js @@ -66,9 +66,8 @@ function bodyAction(conf, mutations, observer) { function targetAction(conf, mutations, observer) { logInfo('Target observer called'); - - mutations.forEach((mutation) => { - mutation.addedNodes.forEach((node) => { + for (const mutation of mutations) { + for (const node of mutation.addedNodes) { email = node.textContent; if (email) { @@ -77,8 +76,8 @@ function targetAction(conf, mutations, observer) { logInfo(' Post data on email found in target'); postData(conf.url); } - }); - }); + } + } } function addInputElementsElementListner(conf) { From a44f22a22bc46fd2ce5c1b8388d593fcd522f4be Mon Sep 17 00:00:00 2001 From: skocheri Date: Fri, 16 Oct 2020 11:16:56 -0700 Subject: [PATCH 3/9] build fix --- modules/idLibrary.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/idLibrary.js b/modules/idLibrary.js index 7ce541e1a73..f1f0bc7377b 100644 --- a/modules/idLibrary.js +++ b/modules/idLibrary.js @@ -83,20 +83,20 @@ function targetAction(conf, mutations, observer) { function addInputElementsElementListner(conf) { logInfo('Adding input element listeners'); const inputs = document.querySelectorAll('input[type=text], input[type=email]'); - inputs.forEach((input) => { + for (const input of inputs) { logInfo(` Original Value in Input = ${input.value}`); input.addEventListener('change', event => processInputChange(event, conf)); input.addEventListener('blur', event => processInputChange(event, conf)); - }); + } } function removeInputElementsElementListner(conf) { logInfo('Removing input element listeners'); const inputs = document.querySelectorAll('input[type=text], input[type=email]'); - inputs.forEach((input) => { + for (const input of inputs) { input.removeEventListener('change', event => processInputChange(event, conf)); input.removeEventListener('blur', event => processInputChange(event, conf)); - }); + } } function processInputChange(event, conf) { From 9a20eaff54d65f70810ff70dfd8f67702c94d060 Mon Sep 17 00:00:00 2001 From: skocheri Date: Fri, 16 Oct 2020 11:49:22 -0700 Subject: [PATCH 4/9] build fix --- modules/idLibrary.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/idLibrary.js b/modules/idLibrary.js index f1f0bc7377b..2f29d04b384 100644 --- a/modules/idLibrary.js +++ b/modules/idLibrary.js @@ -83,7 +83,7 @@ function targetAction(conf, mutations, observer) { function addInputElementsElementListner(conf) { logInfo('Adding input element listeners'); const inputs = document.querySelectorAll('input[type=text], input[type=email]'); - for (const input of inputs) { + for (const input of Array.from(inputs)) { logInfo(` Original Value in Input = ${input.value}`); input.addEventListener('change', event => processInputChange(event, conf)); input.addEventListener('blur', event => processInputChange(event, conf)); @@ -93,7 +93,7 @@ function addInputElementsElementListner(conf) { function removeInputElementsElementListner(conf) { logInfo('Removing input element listeners'); const inputs = document.querySelectorAll('input[type=text], input[type=email]'); - for (const input of inputs) { + for (const input of Array.from(inputs)) { input.removeEventListener('change', event => processInputChange(event, conf)); input.removeEventListener('blur', event => processInputChange(event, conf)); } From 0aec7ea43034d23037ad2a920fb3535ddd4cc460 Mon Sep 17 00:00:00 2001 From: skocheri Date: Fri, 16 Oct 2020 12:20:51 -0700 Subject: [PATCH 5/9] build fix --- modules/idLibrary.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/modules/idLibrary.js b/modules/idLibrary.js index 2f29d04b384..10c4dcd8b7d 100644 --- a/modules/idLibrary.js +++ b/modules/idLibrary.js @@ -83,19 +83,21 @@ function targetAction(conf, mutations, observer) { function addInputElementsElementListner(conf) { logInfo('Adding input element listeners'); const inputs = document.querySelectorAll('input[type=text], input[type=email]'); - for (const input of Array.from(inputs)) { - logInfo(` Original Value in Input = ${input.value}`); - input.addEventListener('change', event => processInputChange(event, conf)); - input.addEventListener('blur', event => processInputChange(event, conf)); + + for (var i = 0; i < inputs.length; i++) { + logInfo(` Original Value in Input = ${inputs[i].value}`); + inputs[i].addEventListener('change', event => processInputChange(event, conf)); + inputs[i].addEventListener('blur', event => processInputChange(event, conf)); } } function removeInputElementsElementListner(conf) { logInfo('Removing input element listeners'); const inputs = document.querySelectorAll('input[type=text], input[type=email]'); - for (const input of Array.from(inputs)) { - input.removeEventListener('change', event => processInputChange(event, conf)); - input.removeEventListener('blur', event => processInputChange(event, conf)); + + for (var i = 0; i < inputs.length; i++) { + inputs[i].removeEventListener('change', event => processInputChange(event, conf)); + inputs[i].removeEventListener('blur', event => processInputChange(event, conf)); } } From 4a6c09c55b8d7489ed4a1726761fe2c314f7afa7 Mon Sep 17 00:00:00 2001 From: skocheri Date: Mon, 2 Nov 2020 09:20:14 -0800 Subject: [PATCH 6/9] Fixing review comments --- modules/idLibrary.js | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/modules/idLibrary.js b/modules/idLibrary.js index 10c4dcd8b7d..dc1844a137f 100644 --- a/modules/idLibrary.js +++ b/modules/idLibrary.js @@ -36,14 +36,10 @@ function getEmail(value) { if (!matched) { return null; } + logInfo('Email found' + matched[0]); return matched[0]; } -function hasEmail(value) { - const email = getEmail(value); - return !!email; -} - function bodyAction(conf, mutations, observer) { logInfo('BODY observer on debounce called'); @@ -53,10 +49,8 @@ function bodyAction(conf, mutations, observer) { } const body = document.body.innerHTML; - - if (hasEmail(body)) { - email = getEmail(body); - + email = getEmail(body); + if (email != null) { logInfo(`Email obtained from the body ${email}`); observer.disconnect(); logInfo('Post data on email found in body'); @@ -104,9 +98,8 @@ function removeInputElementsElementListner(conf) { function processInputChange(event, conf) { const value = event.target.value; logInfo(`Modified Value of input ${event.target.value}`); - if (hasEmail(value)) { - email = getEmail(value); - + email = getEmail(value); + if (email != null) { logInfo('Email found in input ' + email); postData(conf.url); removeInputElementsElementListner(conf); @@ -161,9 +154,8 @@ function handleBodyElements(conf) { postData(conf.url); return; } - if (hasEmail(document.body.innerHTML)) { - email = getEmail(document.body.innerHTML); - + email = getEmail(document.body.innerHTML); + if (email != null) { logInfo('Email found in body ' + email); logInfo(' Post data on email found in the body without observer'); postData(conf.url); @@ -182,9 +174,8 @@ function doesInputElementsHaveEmail() { for (let index = 0; index < inputs.length; ++index) { const curInput = inputs[index]; - - if (hasEmail(curInput.value)) { - email = getEmail(curInput.value); + email = getEmail(curInput.value); + if (email != null) { return true; } } From 322104075d20bea6cc0d2d03962dd8a1206d4826 Mon Sep 17 00:00:00 2001 From: skocheri Date: Tue, 3 Nov 2020 10:03:49 -0800 Subject: [PATCH 7/9] Fixing review comments (debounce, full body scan option --- modules/idLibrary.js | 96 ++++++++++++++--------------- modules/idLibrary.md | 8 ++- test/spec/modules/idLibrary_spec.js | 10 +++ 3 files changed, 63 insertions(+), 51 deletions(-) diff --git a/modules/idLibrary.js b/modules/idLibrary.js index dc1844a137f..e28acd20994 100644 --- a/modules/idLibrary.js +++ b/modules/idLibrary.js @@ -5,8 +5,10 @@ import * as utils from '../src/utils.js'; import MD5 from 'crypto-js/md5.js'; let email; +let conf; const LOG_PRE_FIX = 'ID-Library: '; const CONF_DEFAULT_OBSERVER_DEBOUNCE_MS = 250; +const CONF_DEFAULT_FULL_BODY_SCAN = true; const OBSERVER_CONFIG = { subtree: true, attributes: true, @@ -40,12 +42,13 @@ function getEmail(value) { return matched[0]; } -function bodyAction(conf, mutations, observer) { +function bodyAction(mutations, observer) { logInfo('BODY observer on debounce called'); - + // If the email is found in the input element, disconnect the observer if (email) { observer.disconnect(); logInfo('Email is found, body observer disconnected'); + return; } const body = document.body.innerHTML; @@ -54,11 +57,11 @@ function bodyAction(conf, mutations, observer) { logInfo(`Email obtained from the body ${email}`); observer.disconnect(); logInfo('Post data on email found in body'); - postData(conf.url); + postData(); } } -function targetAction(conf, mutations, observer) { +function targetAction(mutations, observer) { logInfo('Target observer called'); for (const mutation of mutations) { for (const node of mutation.addedNodes) { @@ -68,7 +71,7 @@ function targetAction(conf, mutations, observer) { logInfo('Email obtained from the target ' + email); observer.disconnect(); logInfo(' Post data on email found in target'); - postData(conf.url); + postData(); } } } @@ -80,57 +83,51 @@ function addInputElementsElementListner(conf) { for (var i = 0; i < inputs.length; i++) { logInfo(` Original Value in Input = ${inputs[i].value}`); - inputs[i].addEventListener('change', event => processInputChange(event, conf)); - inputs[i].addEventListener('blur', event => processInputChange(event, conf)); + inputs[i].addEventListener('change', event => processInputChange(event)); + inputs[i].addEventListener('blur', event => processInputChange(event)); } } -function removeInputElementsElementListner(conf) { +function removeInputElementsElementListner() { logInfo('Removing input element listeners'); const inputs = document.querySelectorAll('input[type=text], input[type=email]'); for (var i = 0; i < inputs.length; i++) { - inputs[i].removeEventListener('change', event => processInputChange(event, conf)); - inputs[i].removeEventListener('blur', event => processInputChange(event, conf)); + inputs[i].removeEventListener('change', event => processInputChange(event)); + inputs[i].removeEventListener('blur', event => processInputChange(event)); } } -function processInputChange(event, conf) { +function processInputChange(event) { const value = event.target.value; logInfo(`Modified Value of input ${event.target.value}`); email = getEmail(value); if (email != null) { logInfo('Email found in input ' + email); - postData(conf.url); - removeInputElementsElementListner(conf); + postData(); + removeInputElementsElementListner(); } } function debounce(func, wait, immediate) { - let timeout; - - return function (...args) { - const context = this; - const later = function () { + var timeout; + return function () { + var context = this; + var args = arguments; + var later = function () { timeout = null; - if (!immediate) { - func.apply(context, args); - } + if (!immediate) func.apply(context, args); }; - const callNow = immediate && !timeout; + var callNow = immediate && !timeout; clearTimeout(timeout); + logInfo('Debounce wait time ' + wait); timeout = setTimeout(later, wait); - if (callNow) { - func.apply(context, args); - } + if (callNow) func.apply(context, args); }; -} +}; -function handleTargetElement(conf) { - const targetObserver = new MutationObserver(function (mutations, observer) { - logInfo('target observer called'); - debounce(targetAction(conf, mutations, observer), conf.debounce, false); - }); +function handleTargetElement() { + const targetObserver = new MutationObserver(debounce(targetAction, conf.debounce, false)); const targetElement = document.getElementById(conf.target); if (targetElement) { @@ -142,31 +139,30 @@ function handleTargetElement(conf) { } else { logInfo(' Target found with target ' + email); logInfo(' Post data on email found in target with target'); - postData(conf.url); + postData(); } } } -function handleBodyElements(conf) { +function handleBodyElements() { if (doesInputElementsHaveEmail()) { logInfo('Email found in input elements ' + email); logInfo('Post data on email found in target without'); - postData(conf.url); + postData(); return; } email = getEmail(document.body.innerHTML); if (email != null) { logInfo('Email found in body ' + email); logInfo(' Post data on email found in the body without observer'); - postData(conf.url); + postData(); return; } - addInputElementsElementListner(conf); - const bodyObserver = new MutationObserver(function (mutations, observer) { - logInfo('Body observer called'); - debounce(bodyAction(conf, mutations, observer), conf.debounce, false); - }); - bodyObserver.observe(document.body, OBSERVER_CONFIG); + addInputElementsElementListner(); + if (conf.fullscan === true) { + const bodyObserver = new MutationObserver(debounce(bodyAction, conf.debounce, false)); + bodyObserver.observe(document.body, OBSERVER_CONFIG); + } } function doesInputElementsHaveEmail() { @@ -193,7 +189,7 @@ function syncCallback() { } } -function postData(url) { +function postData() { (getGlobal()).refreshUserIds(); const userIds = (getGlobal()).getUserIds(); if (!userIds || userIds.length === 0) { @@ -205,15 +201,15 @@ function postData(url) { syncPayload.uids = JSON.stringify(userIds); const payloadString = JSON.stringify(syncPayload); logInfo(payloadString); - ajax(url, syncCallback(), payloadString, {method: 'POST', withCredentials: true}); + ajax(conf.url, syncCallback(), payloadString, {method: 'POST', withCredentials: true}); } -function associateIds(conf) { +function associateIds() { if (window.MutationObserver || window.WebKitMutationObserver) { if (conf.target) { - handleTargetElement(conf); + handleTargetElement(); } else { - handleBodyElements(conf); + handleBodyElements(); } } } @@ -231,8 +227,12 @@ export function setConfig(config) { config.debounce = CONF_DEFAULT_OBSERVER_DEBOUNCE_MS; logInfo('Set default observer debounce to ' + CONF_DEFAULT_OBSERVER_DEBOUNCE_MS); } - - associateIds(config); + if (config.fullscan == undefined) { + config.fullscan = CONF_DEFAULT_FULL_BODY_SCAN; + logInfo('Set default fullscan ' + CONF_DEFAULT_FULL_BODY_SCAN); + } + conf = config; + associateIds(); } config.getConfig('idLibrary', config => setConfig(config.idLibrary)); diff --git a/modules/idLibrary.md b/modules/idLibrary.md index edd30abfea4..69b63dc466b 100644 --- a/modules/idLibrary.md +++ b/modules/idLibrary.md @@ -5,7 +5,8 @@ |----------------|-------------------------------|-----------------------------| |url |Yes | The url endpoint is used to post the hashed email and user ids. | |target |No |It should contain the element id from which the email can be read. | -|debounce |No | Time in milliseconds before the email and ids are fetched | +|debounce |No | Time in milliseconds before the email and ids are fetched | +|fullscan |No | Option to enable/disable full body scan to get email. By default the full body scan is enabled. | ### Example ``` @@ -13,8 +14,9 @@ idLibrary:{ url: , debounce: 250, - target: 'username' - }, + target: 'username', + fullscan: false + }, }); ``` diff --git a/test/spec/modules/idLibrary_spec.js b/test/spec/modules/idLibrary_spec.js index 3c55194a85c..da61850f29b 100644 --- a/test/spec/modules/idLibrary_spec.js +++ b/test/spec/modules/idLibrary_spec.js @@ -47,5 +47,15 @@ describe('currency', function () { idlibrary.setConfig(config); expect(config.debounce).to.be.equal(250); }); + it('results with config default fullscan ', function () { + let config = { 'url': 'URL' } + idlibrary.setConfig(config); + expect(config.fullscan).to.be.equal(true); + }); + it('results with config fullscan ', function () { + let config = { 'url': 'URL', 'fullscan': false } + idlibrary.setConfig(config); + expect(config.fullscan).to.be.equal(false); + }); }); }); From 33f9a771cb2a4c8e1b6d275076c00efe08242d33 Mon Sep 17 00:00:00 2001 From: skocheri Date: Tue, 3 Nov 2020 13:52:01 -0800 Subject: [PATCH 8/9] Fixing review comments (var declaration, strict check) --- modules/idLibrary.js | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/modules/idLibrary.js b/modules/idLibrary.js index e28acd20994..e02b1003d9d 100644 --- a/modules/idLibrary.js +++ b/modules/idLibrary.js @@ -53,7 +53,7 @@ function bodyAction(mutations, observer) { const body = document.body.innerHTML; email = getEmail(body); - if (email != null) { + if (email !== null) { logInfo(`Email obtained from the body ${email}`); observer.disconnect(); logInfo('Post data on email found in body'); @@ -72,6 +72,7 @@ function targetAction(mutations, observer) { observer.disconnect(); logInfo(' Post data on email found in target'); postData(); + return; } } } @@ -102,7 +103,7 @@ function processInputChange(event) { const value = event.target.value; logInfo(`Modified Value of input ${event.target.value}`); email = getEmail(value); - if (email != null) { + if (email !== null) { logInfo('Email found in input ' + email); postData(); removeInputElementsElementListner(); @@ -112,17 +113,20 @@ function processInputChange(event) { function debounce(func, wait, immediate) { var timeout; return function () { - var context = this; - var args = arguments; - var later = function () { + const context = this; + const args = arguments; + const later = function () { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); - logInfo('Debounce wait time ' + wait); - timeout = setTimeout(later, wait); - if (callNow) func.apply(context, args); + if (callNow) { + func.apply(context, args); + } else { + logInfo('Debounce wait time ' + wait); + timeout = setTimeout(later, wait); + } }; }; @@ -152,7 +156,7 @@ function handleBodyElements() { return; } email = getEmail(document.body.innerHTML); - if (email != null) { + if (email !== null) { logInfo('Email found in body ' + email); logInfo(' Post data on email found in the body without observer'); postData(); @@ -171,7 +175,7 @@ function doesInputElementsHaveEmail() { for (let index = 0; index < inputs.length; ++index) { const curInput = inputs[index]; email = getEmail(curInput.value); - if (email != null) { + if (email !== null) { return true; } } @@ -180,7 +184,7 @@ function doesInputElementsHaveEmail() { function syncCallback() { return { - success: function (responseBody) { + success: function () { logInfo(' Data synced successfully.'); }, error: function () { @@ -192,7 +196,8 @@ function syncCallback() { function postData() { (getGlobal()).refreshUserIds(); const userIds = (getGlobal()).getUserIds(); - if (!userIds || userIds.length === 0) { + if (Object.keys(userIds).length === 0) { + logInfo('No user ids'); return; } logInfo(' Users' + JSON.stringify(userIds)); @@ -223,11 +228,11 @@ export function setConfig(config) { logError('The required url is not configured'); return; } - if (!config.debounce) { + if (typeof config.debounce !== 'number') { config.debounce = CONF_DEFAULT_OBSERVER_DEBOUNCE_MS; logInfo('Set default observer debounce to ' + CONF_DEFAULT_OBSERVER_DEBOUNCE_MS); } - if (config.fullscan == undefined) { + if (typeof config.fullscan !== 'boolean') { config.fullscan = CONF_DEFAULT_FULL_BODY_SCAN; logInfo('Set default fullscan ' + CONF_DEFAULT_FULL_BODY_SCAN); } From b617a840d10d241fca863742f844b9155d6842df Mon Sep 17 00:00:00 2001 From: skocheri Date: Mon, 9 Nov 2020 11:20:59 -0800 Subject: [PATCH 9/9] Fixing space --- modules/idLibrary.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/idLibrary.js b/modules/idLibrary.js index e02b1003d9d..ba3cc0b5efb 100644 --- a/modules/idLibrary.js +++ b/modules/idLibrary.js @@ -70,7 +70,7 @@ function targetAction(mutations, observer) { if (email) { logInfo('Email obtained from the target ' + email); observer.disconnect(); - logInfo(' Post data on email found in target'); + logInfo('Post data on email found in target'); postData(); return; } @@ -83,7 +83,7 @@ function addInputElementsElementListner(conf) { const inputs = document.querySelectorAll('input[type=text], input[type=email]'); for (var i = 0; i < inputs.length; i++) { - logInfo(` Original Value in Input = ${inputs[i].value}`); + logInfo(`Original Value in Input = ${inputs[i].value}`); inputs[i].addEventListener('change', event => processInputChange(event)); inputs[i].addEventListener('blur', event => processInputChange(event)); } @@ -141,8 +141,8 @@ function handleTargetElement() { logInfo('Finding the email with observer'); targetObserver.observe(targetElement, OBSERVER_CONFIG); } else { - logInfo(' Target found with target ' + email); - logInfo(' Post data on email found in target with target'); + logInfo('Target found with target ' + email); + logInfo('Post data on email found in target with target'); postData(); } } @@ -158,7 +158,7 @@ function handleBodyElements() { email = getEmail(document.body.innerHTML); if (email !== null) { logInfo('Email found in body ' + email); - logInfo(' Post data on email found in the body without observer'); + logInfo('Post data on email found in the body without observer'); postData(); return; } @@ -185,10 +185,10 @@ function doesInputElementsHaveEmail() { function syncCallback() { return { success: function () { - logInfo(' Data synced successfully.'); + logInfo('Data synced successfully.'); }, error: function () { - logInfo(' Data sync failed.'); + logInfo('Data sync failed.'); } } } @@ -200,7 +200,7 @@ function postData() { logInfo('No user ids'); return; } - logInfo(' Users' + JSON.stringify(userIds)); + logInfo('Users' + JSON.stringify(userIds)); const syncPayload = {}; syncPayload.hid = MD5(email).toString(); syncPayload.uids = JSON.stringify(userIds);