var heatmaps = (function () {
"use strict";
var tmpl = new Template(),
mustache = new itsMustache(),
render = mustache.render;
function Heatmaps(target, data) {
var events = new EventManager(),
containers = {},
ads = [],
index = getElementFromString(tmpl.index),
closed = false;
this.exit = exit;
init();
function init() {
if (!data.adsList) {
// TODO: Do empty ads notice
console.error("empty ads list")
return;
}
if (!data.clicks) {
data.clicks = [];
}
data.adsList.forEach(processAd);
target.appendChild(index);
}
function processAd(ad) {
var key = ad.data.width + "/" + ad.data.height,
container = containers[key];
if (!container) {
container = containers[key] = getElementFromString(tmpl.container);
container.querySelector("h2").textContent = key;
index.appendChild(container);
}
ads.push(new Ad(events, container, data, ad.id, ad.data));
}
function exit() {
if (closed) {
return;
}
ads.forEach(function (ad) {
ad.exit();
});
events.reset()
removeChild(target, index);
events = index = null;
closed = true;
}
}
function ReportItem(events, db, tgt, id, click, index) {
var r = document.createElement("report-item"),
ts = document.createElement("row"),
uuid = document.createElement("row"),
ttc = document.createElement("row"),
d = new Date(click.ts * 1000),
sk = db.Sub("activeRow", onRowUpdate),
closed = false;
this.exit = exit;
ts.innerHTML = "" + d.toString() + "";
uuid.innerHTML = "UUID: " + click.uuid;
ttc.innerHTML = "Time to click: " + click.ttc + " milliseconds";
events.add(r, "click", onClick, id);
r.appendChild(ts);
r.appendChild(uuid);
r.appendChild(ttc);
tgt.appendChild(r);
function onClick(evt) {
db.Put("activeRow", index);
}
function onRowUpdate(evt) {
if (evt !== index) {
r.classList.remove("active");
} else {
r.classList.add("active");
}
}
function exit() {
if (closed) {
return;
}
db.Unsub("activeRow", sk);
removeChild(tgt, r);
closed = true;
}
}
function Ad(events, tgt, req, id, data) {
var item = getElementFromString(render(tmpl.item, data)),
hm = item.querySelector(".heatmap"),
img = item.querySelector("img"),
rpt = item.querySelector("reporting"),
db = psStore(),
sk = db.Sub("activeRow", onRowUpdate),
clicks = [],
reportingItems = [],
cm = null,
expanded = false,
activeRow = -1,
closed = false;
this.exit = exit;
events.add(img, "load", onLoad, id);
events.add(img, "error", onError, id);
tgt.appendChild(item);
function exit() {
if (closed) {
return;
}
db.Unsub("activeRow", sk);
reportingItems.forEach(function (ri) {
ri.exit();
});
events.removeByTag(id);
removeChild(tgt, item);
if (tgt.childNodes.length <= 1) {
removeChild(tgt.parentNode, tgt);
}
closed = true;
}
function onLoad(evt) {
// Declare ClickMap since our image has loaded
cm = ClickMap.New(hm);
if (!!req.clicks) {
// Only perform this filter if request clicks are not null
clicks = req.clicks.filter(isAd);
}
if (!clicks || clicks.length === 0) {
item.classList.add("noClicks");
return;
}
cm.Load(clicks);
clicks.forEach(function (t, i) {
reportingItems.push(new ReportItem(events, db, rpt, id, t, i));
});
events.add(hm, "click", onClick, id);
}
function onError(evt) {
console.error("Error!", evt);
exit();
}
function onClick(evt) {
var x = evt.layerX,
y = evt.layerY,
match = cm.GetMatch(x, y);
if (match > -1) {
db.Put("activeRow", match);
}
if (!expanded) {
expanded = true;
item.style.height = item.getClientRects()[0].height + 300 + "px";
} else if (match === -1) {
expanded = false;
item.style.height = item.getClientRects()[0].height - 300 + "px";
}
}
function onRowUpdate(evt) {
if (evt === activeRow && evt !== -1) {
db.Put("activeRow", -1);
return;
}
cm.SetActive(evt);
activeRow = evt;
}
function isAd(click) {
return click.adID === id;
}
}
function Template() {
var wh = 'style="height: {{ height }}px; width: {{ width }}px;"',
img = '',
rpt = '