Skip to content

Commit

Permalink
Merge pull request #148 from driveback/feature/custom-events
Browse files Browse the repository at this point in the history
Feature/custom events
  • Loading branch information
ConstantineYurevich authored Jun 23, 2017
2 parents db9f971 + 3636606 commit dde5489
Show file tree
Hide file tree
Showing 31 changed files with 571 additions and 211 deletions.
128 changes: 94 additions & 34 deletions src/EventManager.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import clone from './functions/clone';
import deleteProperty from './functions/deleteProperty.js';
import size from './functions/size.js';
import after from './functions/after.js';
import jsonIsEqual from './functions/jsonIsEqual.js';
import deleteProperty from './functions/deleteProperty';
import size from './functions/size';
import after from './functions/after';
import jsonIsEqual from './functions/jsonIsEqual';
import { error as errorLog } from './functions/safeConsole';
import DDHelper from './DDHelper.js';
import EventDataEnricher from './enrichments/EventDataEnricher.js';
import DDHelper from './DDHelper';
import EventDataEnricher from './enrichments/EventDataEnricher';
import CustomEvent from './events/CustomEvent';
import { VIEWED_PAGE } from './events/semanticEvents';

let _callbacks = {};
Expand All @@ -16,6 +17,7 @@ let _checkForChangesIntervalId;
let _viewabilityTracker;
let _isInitialized = false;
let _sendViewedPageEvent = false;
const _customEvents = [];

function _getCopyWithoutEvents(digitalData) {
// not a deep copy for performance optimization and removal of events and changes
Expand All @@ -41,9 +43,33 @@ class EventManager {
_previousDigitalData = _getCopyWithoutEvents(_digitalData);
}

import(eventsConfig) {
eventsConfig = eventsConfig || [];
for (const eventConfig of eventsConfig) {
const customEvent = new CustomEvent(
eventConfig.name,
eventConfig.trigger,
eventConfig.event || eventConfig.cssSelector,
eventConfig.handler,
_digitalData,
this
);
_customEvents.push(customEvent);
}
}

addEvent(name, trigger, setting, handler) {
const customEvent = new CustomEvent(name, trigger, setting, handler, _digitalData, this);
_customEvents.push(customEvent);
}

initialize() {
const events = _digitalData.events;
const changes = _digitalData.changes;

// initialize custom events tracking
for (const customEvent of _customEvents) {
customEvent.track();
}

// process callbacks
this.addEarlyCallbacks();
Expand All @@ -54,28 +80,58 @@ class EventManager {
};

// process events
this.fireUnfiredEvents();
// TODO: refactoring
if (this.isViewedPageSent()) {
this.fireUnfiredEvents();
this.enableEventsTracking();
} else if (_sendViewedPageEvent && !this.isViewedPageSent()) {
this.addViewedPageEvent();
this.fireUnfiredEvents();
this.enableEventsTracking();
} else {
events.push = (event) => {
// waiting for "Viewed Page" event
if (event.name === VIEWED_PAGE) {
this.addViewedPageEvent(event);
this.enableEventsTracking();
this.fireUnfiredEvents();
} else {
events[events.length] = event;
}
};
}

// process changes
this.applyEarlyChanges();
this.enableChangesTracking();

if (_viewabilityTracker) {
_viewabilityTracker.initialize();
}

_isInitialized = true;
}

enableEventsTracking() {
const events = _digitalData.events;
events.push = (event) => {
events[events.length] = event;
this.fireEvent(event);
};
}

enableChangesTracking() {
const changes = _digitalData.changes;

// process changes
this.applyEarlyChanges();
changes.push = (changeInfo) => {
changes[changes.length] = changeInfo;
this.applyChange(changeInfo);
};

if (_viewabilityTracker) {
_viewabilityTracker.initialize();
}
_checkForChangesIntervalId = setInterval(() => {
this.fireDefine();
this.checkForChanges();
}, 100);

_isInitialized = true;
}

setSendViewedPageEvent(sendViewedPageEvent) {
Expand Down Expand Up @@ -117,11 +173,28 @@ class EventManager {
}
const handler = callbackInfo[2];
this.on(callbackInfo[1], handler, processPastEvents);
} if (callbackInfo[0] === 'off') {
} else if (callbackInfo[0] === 'off') {
// TODO
}
}

isViewedPageSent() {
const events = _digitalData.events;
for (const event of events) {
if (event.name === VIEWED_PAGE) {
return true;
}
}
return false;
}

addViewedPageEvent(event) {
if (!event) {
event = { name: VIEWED_PAGE, source: 'DDManager' };
}
_digitalData.events.unshift(event);
}

fireDefine() {
let callback;
if (_callbacks.define && _callbacks.define.length > 0) {
Expand Down Expand Up @@ -202,15 +275,17 @@ class EventManager {
}

fireEvent(event) {
event.timestamp = Date.now();
if (!event.timestamp) { // do not override if defined in unit tests
event.timestamp = Date.now();
}

if (!this.beforeFireEvent(event)) {
return false;
}

if (_callbacks.event) {
const results = [];
const errors = [];

const ready = after(size(_callbacks.event), () => {
if (typeof event.callback === 'function') {
event.callback(results, errors);
Expand Down Expand Up @@ -289,22 +364,7 @@ class EventManager {

fireUnfiredEvents() {
const events = _digitalData.events;
let event;

if (_sendViewedPageEvent) {
let viewedPageEventIsSent = false;
for (event of events) {
if (event.name === VIEWED_PAGE) {
viewedPageEventIsSent = true;
break;
}
}
if (!viewedPageEventIsSent) {
events.unshift({ name: VIEWED_PAGE, source: 'DDManager' });
}
}

for (event of events) {
for (const event of events) {
if (!event.hasFired) {
this.fireEvent(event);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Storage
const info = store.get(key);
if (info !== undefined) {
if (info.val !== undefined && info.exp && info.time) {
if (Date.now() - info.time > info.exp) {
if ((Date.now() - info.time) > info.exp) {
store.rm(key);
return undefined;
}
Expand Down
7 changes: 6 additions & 1 deletion src/ddManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ ddManager = {
});

// initialize custom enrichments
_customEnricher = new CustomEnricher(_ddStorage);
_customEnricher = new CustomEnricher(_digitalData, _ddStorage);
_customEnricher.import(settings.enrichments);

// initialize event manager
Expand All @@ -336,6 +336,7 @@ ddManager = {
}
_customEnricher.enrichDigitalData(_digitalData, event);
}]);
_eventManager.import(settings.events); // import custom events
_eventManager.setSendViewedPageEvent(settings.sendViewedPageEvent);
_eventManager.setViewabilityTracker(new ViewabilityTracker({
websiteMaxWidth: settings.websiteMaxWidth,
Expand Down Expand Up @@ -418,6 +419,10 @@ ddManager = {
_customEnricher.addEnrichment(type, prop, handler, options);
},

addEvent: (name, trigger, setting, handler) => {
_eventManager.addEvent(name, trigger, setting, handler);
},

reset: () => {
if (_ddStorage) {
_ddStorage.clear();
Expand Down
45 changes: 27 additions & 18 deletions src/enrichments/CustomEnricher.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,6 @@ const storage = {
},
};

const prepareCollection = (type, trigger, event) => {
if (trigger === ENRICHMENT_TRIGGER_EVENT) {
if (!storage[type][trigger][event]) {
storage[type][trigger][event] = new CustomEnrichmentsCollection(type, trigger, event);
}
return storage[type][trigger][event];
}
if (!storage[type][trigger]) {
storage[type][trigger] = new CustomEnrichmentsCollection(type, trigger);
}
return storage[type][trigger];
};

const checkEnrichment = (enrichment) => {
return (
typeof enrichment === 'object' &&
Expand All @@ -34,8 +21,9 @@ const checkEnrichment = (enrichment) => {
};

class CustomEnrichments {
constructor(ddStorage) {
constructor(digitalData, ddStorage) {
this.ddStorage = ddStorage;
this.digitalData = digitalData;
}

import(enrichments) {
Expand All @@ -52,10 +40,10 @@ class CustomEnrichments {
const enrichment = { prop, handler, options };
let collection;
if (events.length === 0) {
collection = prepareCollection(type, ENRICHMENT_TRIGGER_INIT);
collection = this.prepareCollection(type, ENRICHMENT_TRIGGER_INIT);
} else {
for (const eventName of events) {
collection = prepareCollection(type, ENRICHMENT_TRIGGER_EVENT, eventName);
collection = this.prepareCollection(type, ENRICHMENT_TRIGGER_EVENT, eventName);
}
}
collection.addEnrichment(enrichment, this.ddStorage);
Expand All @@ -64,15 +52,36 @@ class CustomEnrichments {
enrichDigitalData(digitalData, event = null) {
let collection;
if (!event) {
collection = prepareCollection(ENRICHMENT_TYPE_DIGITAL_DATA, ENRICHMENT_TRIGGER_INIT);
collection = this.prepareCollection(ENRICHMENT_TYPE_DIGITAL_DATA, ENRICHMENT_TRIGGER_INIT);
collection.enrich(digitalData, [event], true);
} else {
const eventName = event.name;
collection = prepareCollection(ENRICHMENT_TYPE_DIGITAL_DATA, ENRICHMENT_TRIGGER_EVENT, eventName);
collection = this.prepareCollection(ENRICHMENT_TYPE_DIGITAL_DATA, ENRICHMENT_TRIGGER_EVENT, eventName);
collection.enrich(digitalData, [event]);
}
}

prepareCollection(type, trigger, event) {
if (trigger === ENRICHMENT_TRIGGER_EVENT) {
if (!storage[type][trigger][event]) {
storage[type][trigger][event] = this.newCollection(type, trigger, event);
}
return storage[type][trigger][event];
}
if (!storage[type][trigger]) {
storage[type][trigger] = this.newCollection(type, trigger);
}
return storage[type][trigger];
}

newCollection(type, trigger, event) {
const collection = new CustomEnrichmentsCollection(type, trigger, event);
collection.setDigitalData(this.digitalData);
collection.setDDStorage(this.ddStorage);

return collection;
}

reset() {
storage[ENRICHMENT_TYPE_DIGITAL_DATA] = {
[ENRICHMENT_TRIGGER_INIT]: undefined,
Expand Down
7 changes: 4 additions & 3 deletions src/enrichments/CustomEnrichment.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { error as errorLog } from './../functions/safeConsole';
import { setProp } from './../functions/dotProp';

class CustomEnrichment {
constructor(prop, handler, options, collection, ddStorage) {
constructor(prop, handler, options, collection) {
this.prop = prop;
this.handler = handler;
this.options = options || {};
this.collection = collection;
this.ddStorage = ddStorage;
this.digitalData = collection.getDigitalData();
this.ddStorage = collection.getDDStorage();

this.done = false;
this.recursionFreeze = false;
Expand Down Expand Up @@ -38,7 +39,7 @@ class CustomEnrichment {
}
}

const handler = new EnrichmentHandler(this.handler, target, args);
const handler = new EnrichmentHandler(this.handler, this.digitalData, args);
let value;
try {
value = handler.run();
Expand Down
20 changes: 18 additions & 2 deletions src/enrichments/CustomEnrichmentsCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,28 @@ class CustomEnrichmentsCollection {
this.enrichmentsIndex = {};
}

addEnrichment(enrichmentConfig, ddStorage) {
setDigitalData(digitalData) {
this.digitalData = digitalData;
}

getDigitalData() {
return this.digitalData;
}

setDDStorage(ddStorage) {
this.ddStorage = ddStorage;
}

getDDStorage() {
return this.ddStorage;
}

addEnrichment(enrichmentConfig) {
const prop = enrichmentConfig.prop;
const handler = enrichmentConfig.handler;
const options = enrichmentConfig.options;

const enrichment = new CustomEnrichment(prop, handler, options, this, ddStorage);
const enrichment = new CustomEnrichment(prop, handler, options, this);
this.enrichments.push(enrichment);
this.enrichmentsIndex[enrichment.prop] = enrichment;
}
Expand Down
6 changes: 3 additions & 3 deletions src/enrichments/EnrichmentHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import cookie from 'js-cookie';
import DDHelper from './../DDHelper';

class EnrichmentHandler {
constructor(handler, digitalData, event) {
constructor(handler, digitalData, args) {
this.handler = handler;
this.event = event;
this.args = args;
this.utils = {
getQueryParam: getQueryParam,
getCookie: cookie.get,
Expand All @@ -17,7 +17,7 @@ class EnrichmentHandler {

run() {
const handlerWithUtils = this.handler.bind(this.utils);
return handlerWithUtils(this.event);
return handlerWithUtils(...this.args);
}
}

Expand Down
Loading

0 comments on commit dde5489

Please sign in to comment.