@swrve/smarttv-sdk
Version:
Swrve marketing engagement platform SDK for SmartTV OTT devices
419 lines (418 loc) • 16.9 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SwrveMessageDisplayManager = void 0;
const SwrveConstants = __importStar(require("../../utils/SwrveConstants"));
const SwrveConstants_1 = require("../../utils/SwrveConstants");
const SwrveFocusManager_1 = __importDefault(require("../../UIElements/SwrveFocusManager"));
const SwrveLogger_1 = __importDefault(require("../../utils/SwrveLogger"));
const TextTemplating_1 = require("../../utils/TextTemplating");
const blacklistedCSSAttributes = [
// strip out attributes used for positioning
"position", "width", "height", "top", "left",
// strip out extra attributes from resources
"uid", "name", "description", "thumbnail", "item_class",
].reduce((idx, prop) => {
idx[prop] = true;
return idx;
}, {});
const defaultStyle = {
opacity: "0.5",
transition: "opacity 150ms ease-out",
};
const defaultFocusStyle = {
opacity: "1",
transition: "opacity 150ms ease-out",
};
class SwrveMessageDisplayManager {
constructor(platform, config, resourceManager) {
this.screenCenterWidth = 0;
this.screenCenterHeight = 0;
this.onBackButtonClickedCallback = null;
this.onButtonClickedCallback = null;
this.onPageViewedCallback = null;
this.isOpen = false;
this.justClosed = false;
this.currentPageIndex = 0;
this.currentMessagePages = [];
this.sentPageViewEvents = [];
this.sentNavigationEvents = [];
this.imagesCDN = "";
this.scale = 1;
this.onKeydown = (ev) => {
if (!this.isOpen) {
return;
}
ev.preventDefault();
ev.stopImmediatePropagation();
const key = this.keymap[ev.keyCode];
if (key === "Back") {
this.closeMessage();
if (this.onBackButtonClickedCallback) {
this.onBackButtonClickedCallback();
}
}
else if (key && this.focusManager) {
this.focusManager.onKeyPress(key);
}
};
this.onKeyup = (ev) => {
// Closing the message will fire up one last "keyup" event
// This prevents that keyup event from spreading down to the app
if (this.justClosed) {
ev.preventDefault();
ev.stopImmediatePropagation();
this.justClosed = false;
return;
}
};
this.normalStyle = config && config.inAppMessageButtonStyle;
this.focusStyle = config && config.inAppMessageButtonFocusStyle;
this.overrideIAMStyle = config && config.inAppMessageStyleOverride;
this.keymap = platform.getKeymapping();
this.resourceManager = resourceManager;
this.initListener();
}
showMessage(message, parentCampaign, imagesCDN, platform, personalizationProperties) {
var _a, _b;
this.currentPageIndex = 0;
this.currentMessagePages = [];
this.sentPageViewEvents = [];
this.sentNavigationEvents = [];
this.screenCenterWidth = platform.screenWidth / 2;
this.screenCenterHeight = platform.screenHeight / 2;
this.personalizationProperties = personalizationProperties;
const iam = this.getLandscapeFormat(message);
if (!iam)
return;
this.isOpen = true;
this.imagesCDN = imagesCDN || '';
this.scale = (_a = iam.scale) !== null && _a !== void 0 ? _a : 1;
this.createContainer(message.name, iam.color || undefined);
if (iam.pages && ((_b = iam.pages) === null || _b === void 0 ? void 0 : _b.length) > 0) {
this.currentMessagePages = iam.pages;
this.renderPage(this.currentPageIndex, parentCampaign);
}
else {
this.renderContent(iam.images, iam.buttons, parentCampaign);
}
}
onPageViewed(callback) {
this.onPageViewedCallback = callback;
}
onButtonClicked(callback) {
this.onButtonClickedCallback = callback;
}
onBackButtonClicked(callback) {
this.onBackButtonClickedCallback = callback;
}
isIAMShowing() {
return this.isOpen;
}
getSentPageViewEvents() {
return this.sentPageViewEvents;
}
getSentNavigationEvents() {
return this.sentNavigationEvents;
}
closeMessage() {
const container = document.getElementById(SwrveConstants_1.SWRVE_IAM_CONTAINER);
if (container) {
document.body.removeChild(container);
}
this.isOpen = false;
this.justClosed = true;
delete this.focusManager;
}
initListener() {
window.addEventListener("keydown", this.onKeydown, true);
window.addEventListener("keyup", this.onKeyup, true);
}
getLandscapeFormat(message) {
const formats = message.template.formats || null;
if (formats) {
let landscape = null;
formats.forEach(format => {
if (format.orientation === "landscape") {
landscape = format;
}
});
return landscape;
}
else {
return null;
}
}
createFocusManager(buttons) {
return new SwrveFocusManager_1.default(buttons, {
direction: "bidirectional",
onFocus: (btn) => this.applyElementStyle(btn.element, this.getFocusStyle(this.focusStyle, defaultFocusStyle)),
onBlur: (btn) => this.applyElementStyle(btn.element, this.getFocusStyle(this.normalStyle, defaultStyle)),
onKeyPress: ({ button, campaign }, key) => {
if (key === "Enter") {
this.handleButton(button, campaign);
return true;
}
return false;
},
});
}
applyElementStyle(el, style) {
for (const attr in style) {
if (style.hasOwnProperty(attr)) {
el.style[attr] = style[attr];
}
}
}
getFocusStyle(style, defaults) {
let ret = defaults;
if (typeof style === "string") {
if (this.resourceManager) {
const resource = this.resourceManager.getResource(style).toJSON();
if (Object.keys(resource).length !== 0) {
ret = this.sanitizeFocusStyle(resource);
}
}
}
else if (style) {
ret = this.sanitizeFocusStyle(style);
}
return ret;
}
sanitizeFocusStyle(style) {
const ret = {};
for (const key in style) {
if (style.hasOwnProperty(key) && !blacklistedCSSAttributes[key]) {
ret[key] = style[key];
}
}
return ret;
}
appendImages(images) {
images.forEach((image, index) => {
var _a;
const imageElement = document.createElement("img");
imageElement.id = "SwrveImage" + index;
if (image.dynamic_image_url && image.dynamic_image_url.length > 0) {
if (this.personalizationProperties) {
imageElement.src = (_a = this.personalizeText(image.dynamic_image_url, this.personalizationProperties)) !== null && _a !== void 0 ? _a : "";
}
else {
imageElement.src = image.dynamic_image_url;
}
}
else {
imageElement.src = this.imagesCDN + image.image.value;
}
this.addElement(image, imageElement);
});
}
appendButtons(buttons, parentCampaign) {
return buttons.map((button, index) => {
const buttonElement = document.createElement("img");
const buttonStyle = this.getFocusStyle(this.normalStyle, defaultStyle);
const personalizedButton = this.personalizeButton(button);
buttonElement.id = "SwrveButton" + index;
if (personalizedButton.dynamic_image_url && personalizedButton.dynamic_image_url.length > 0) {
buttonElement.src = personalizedButton.dynamic_image_url;
}
else {
buttonElement.src = this.imagesCDN + personalizedButton.image_up.value;
}
buttonElement.style.border = "0px";
buttonElement.onclick = () => this.handleButton(personalizedButton, parentCampaign);
this.applyElementStyle(buttonElement, buttonStyle);
this.addElement(button, buttonElement);
return {
button,
campaign: parentCampaign,
element: buttonElement,
};
});
}
addElement(swrveItem, element) {
if (typeof swrveItem.x.value === "number" && typeof swrveItem.y.value === "number") {
const container = document.getElementById(SwrveConstants_1.SWRVE_IAM_CONTAINER);
let width = element.naturalWidth * this.scale;
let height = element.naturalHeight * this.scale;
if (swrveItem.dynamic_image_url) {
width = swrveItem.w.value * this.scale;
height = swrveItem.h.value * this.scale;
//Aspect fit
const aspectRatio = element.naturalWidth / element.naturalHeight;
if (width / height > aspectRatio) {
width = height * aspectRatio;
}
else {
height = width / aspectRatio;
}
}
const yPos = swrveItem.y.value;
const xPos = swrveItem.x.value;
if (width > height) {
element.style.width = width.toString() + "px";
}
else {
element.style.height = height.toString() + "px";
}
element.style.position = "absolute";
element.style.top = (yPos + (this.screenCenterHeight - (height / 2))).toString() + "px";
element.style.left = (xPos + (this.screenCenterWidth - (width / 2))).toString() + "px";
if (swrveItem.accessibility_text) {
if (this.personalizationProperties) {
const personalizedAltText = this.personalizeText(swrveItem.accessibility_text, this.personalizationProperties);
if (personalizedAltText) {
element.alt = personalizedAltText;
}
}
else {
element.alt = swrveItem.accessibility_text;
}
}
container.appendChild(element);
}
}
handleButton(button, parentCampaign) {
const type = String(button.type.value);
const action = String(button.action.value);
const pageId = this.getCurrentPageId();
const pageName = this.getCurrentPageName();
if (type === SwrveConstants.PAGE_LINK) {
const num = Number(action);
this.changePage(num, parentCampaign);
}
else {
this.closeMessage();
}
if (this.onButtonClickedCallback) {
this.onButtonClickedCallback(button, parentCampaign, pageId, pageName);
}
}
createContainer(name, color) {
const iamContainer = document.createElement("div");
iamContainer.id = SwrveConstants_1.SWRVE_IAM_CONTAINER;
iamContainer.className = SwrveConstants_1.IAM_CSS_CLASS_NAME;
iamContainer.innerHTML = this.overrideIAMStyle || SwrveConstants_1.DEFAULT_IAM_STYLE;
iamContainer.style.backgroundColor = color || "";
document.body.appendChild(iamContainer);
}
changePage(newPageId, parentCampaign) {
const newPageIndex = this.currentMessagePages.findIndex(page => page.page_id === newPageId);
if (newPageIndex !== -1) {
this.currentPageIndex = newPageIndex;
this.renderPage(newPageIndex, parentCampaign);
}
}
renderPage(pageIndex, parentCampaign) {
var _a;
const container = document.getElementById(SwrveConstants_1.SWRVE_IAM_CONTAINER);
if (!container)
return;
// Cache and reapply style content
const styleContent = ((_a = container.querySelector("style")) === null || _a === void 0 ? void 0 : _a.outerHTML) || "";
container.innerHTML = styleContent;
const page = this.currentMessagePages[pageIndex];
if (page) {
this.renderContent(page.images, page.buttons, parentCampaign);
}
}
renderContent(images, buttons, parentCampaign) {
if (images && images.length > 0) {
this.appendImages(images);
}
if (buttons && buttons.length > 0) {
const buttonElements = this.appendButtons(buttons, parentCampaign);
this.focusManager = this.createFocusManager(buttonElements);
this.focusManager.setActiveFirst();
}
if (this.onPageViewedCallback) {
const messageId = parentCampaign.messages && parentCampaign.messages[0] ? parentCampaign.messages[0].id : 0;
const page = this.currentMessagePages[this.currentPageIndex];
if (page) {
this.onPageViewedCallback(messageId, page.page_id, page.page_name);
}
else {
this.onPageViewedCallback(messageId, 0, "");
}
}
}
getCurrentPageId() {
if (!this.currentMessagePages || this.currentMessagePages.length === 0) {
return "";
}
if (this.currentPageIndex < 0 || this.currentPageIndex >= this.currentMessagePages.length) {
return "";
}
const page = this.currentMessagePages[this.currentPageIndex];
return page.page_id.toString();
}
getCurrentPageName() {
if (!this.currentMessagePages || this.currentMessagePages.length === 0) {
return "";
}
if (this.currentPageIndex < 0 || this.currentPageIndex >= this.currentMessagePages.length) {
return "";
}
const page = this.currentMessagePages[this.currentPageIndex];
return page.page_name;
}
personalizeButton(button) {
var _a;
if (this.personalizationProperties == null) {
return button;
}
let personalizedButton = button;
if (button.type.value === SwrveConstants.CUSTOM
&& ((_a = button.action) === null || _a === void 0 ? void 0 : _a.value)
&& typeof button.action.value === 'string') {
const personalizedAction = this.personalizeText(button.action.value, this.personalizationProperties);
if (personalizedAction) {
personalizedButton = JSON.parse(JSON.stringify(button));
personalizedButton.action.value = personalizedAction;
}
}
if (button.dynamic_image_url) {
const personalizedUrl = this.personalizeText(button.dynamic_image_url, this.personalizationProperties);
if (personalizedUrl) {
if (!personalizedButton) {
personalizedButton = JSON.parse(JSON.stringify(button));
}
personalizedButton.dynamic_image_url = personalizedUrl;
}
}
return personalizedButton;
}
personalizeText(text, personalizationProperties) {
if (text != null) {
try {
return TextTemplating_1.TextTemplating.applyTextTemplatingToString(text, personalizationProperties);
}
catch (e) {
SwrveLogger_1.default.error("Could not resolve, error with personalization", e);
}
}
return null;
}
}
exports.SwrveMessageDisplayManager = SwrveMessageDisplayManager;