@braze/web-sdk
Version:
Braze SDK for web sites and other JS platforms.
212 lines (211 loc) • 7.21 kB
JavaScript
import {
getCardId as xt,
markCardAsRead as Rt,
} from "../Card/display/card-display.js";
import { bottomIsInView as x, topIsInView as g } from "../util/dom-utils.js";
import { Card, ControlCard } from "../Card/index.js";
import { cardToHtml as Ht } from "../Card/display/card-display.js";
import { isArray as D } from "../util/code-utils.js";
import { KeyCodes as ie } from "../util/key-codes.js";
import fe from "../l10n/l10n-manager-factory.js";
import { removeSubscription } from "../Core/remove-subscription.js";
import { logger as E, Guid as P } from "../../shared-lib/index.js";
import { BRAZE_ACTION_URI_REGEX as to } from "../util/validation-utils.js";
import {
INELIGIBLE_BRAZE_ACTION_URL_ERROR_TYPES as vt,
ineligibleBrazeActionURLErrorMessage as jt,
getDecodedBrazeAction as eo,
containsUnknownBrazeAction as dt,
} from "../util/braze-actions.js";
import {
bottomHadImpression as kt,
impressOnBottom as d,
impressOnTop as j,
topHadImpression as qt,
} from "./detect-impression.js";
import { SUBSCRIPTION_ID_DATA_ATTRIBUTE as f } from "./constants.js";
import ContentCards from "../ContentCards/content-cards.js";
export const LAST_REQUESTED_REFRESH_DATA_ATTRIBUTE =
"data-last-requested-refresh";
export const SCROLL_LISTENER_ID = "data-listener-id";
export const scrollListeners = {};
export function destroyContentCardsHtml(t) {
t &&
((t.className = t.className.replace("ab-show", "ab-hide")),
setTimeout(() => {
t && t.parentNode && t.parentNode.removeChild(t);
}, ContentCards.cr));
const e = t.getAttribute(f);
null != e && removeSubscription(e);
const n = t.getAttribute("data-listener-id");
null != n &&
(window.removeEventListener("scroll", scrollListeners[n]),
delete scrollListeners[n]);
}
export function generateContentCardsUI(t, e) {
const n = fe.ea(),
o = document.createElement("div");
if (
((o.className = "ab-feed-body"),
o.setAttribute("aria-label", "Feed"),
o.setAttribute("role", "feed"),
null == t.lastUpdated)
) {
const t = document.createElement("div");
t.className = "ab-no-cards-message";
const e = document.createElement("i");
(e.className = "fa fa-spinner fa-spin fa-4x ab-initial-spinner"),
t.appendChild(e),
o.appendChild(t);
} else {
let s = !1;
const r = (e) => t.nr(e);
for (const a of t.cards) {
const i = a instanceof ControlCard;
!i || t.ar()
? (o.appendChild(Ht(a, r, e, n.So())), (s = s || !i))
: E.error(
"Received a control card for a legacy news feed. Control cards are only supported with content cards.",
);
}
if (!s) {
const t = document.createElement("div");
(t.className = "ab-no-cards-message"),
(t.innerHTML = n.get("NO_CARDS_MESSAGE") || ""),
t.setAttribute("role", "article"),
o.appendChild(t);
}
}
return o;
}
export function detectContentCardsImpressions(t, e) {
if (null != t && null != e) {
const n = [],
o = e.querySelectorAll(".ab-card");
t.Qn || (t.Qn = {});
for (let e = 0; e < o.length; e++) {
const s = xt(o[e]),
r = g(o[e]),
a = x(o[e]);
if (t.Qn[s]) {
r || a || Rt(o[e]);
continue;
}
let i = qt(o[e]),
l = kt(o[e]);
const c = i,
f = l;
if (
(!i && r && ((i = !0), j(o[e])), !l && a && ((l = !0), d(o[e])), i && l)
) {
if (c && f) continue;
for (const e of t.cards)
if (e.id === s) {
(t.Qn[e.id] = !0), n.push(e);
break;
}
}
}
n.length > 0 && t.sr(n);
}
}
export function refreshContentCardsUI(t, e) {
if (null == t || null == e) return;
e.setAttribute("aria-busy", "true");
const n = e.querySelectorAll(".ab-refresh-button")[0];
null != n && (n.className += " fa-spin");
const o = new Date().valueOf().toString();
e.setAttribute("data-last-requested-refresh", o),
setTimeout(() => {
if (e.getAttribute("data-last-requested-refresh") === o) {
const t = e.querySelectorAll(".fa-spin");
for (let e = 0; e < t.length; e++)
t[e].className = t[e].className.replace(/fa-spin/g, "");
const n = e.querySelectorAll(".ab-initial-spinner")[0];
if (null != n) {
const t = document.createElement("span");
(t.innerHTML = fe.ea().get("FEED_TIMEOUT_MESSAGE") || ""),
null != n.parentNode &&
(n.parentNode.appendChild(t), n.parentNode.removeChild(n));
}
"true" === e.getAttribute("aria-busy") &&
e.setAttribute("aria-busy", "false");
}
}, ContentCards.Cr),
t.dr();
}
export function contentCardsToHtml(t, e, n) {
const o = document.createElement("div");
(o.className = "ab-feed ab-hide ab-effect-slide"),
o.setAttribute("role", "dialog"),
o.setAttribute("aria-label", "Feed"),
o.setAttribute("tabindex", "-1");
const s = document.createElement("div");
(s.className = "ab-feed-buttons-wrapper"),
s.setAttribute("role", "group"),
o.appendChild(s);
const r = document.createElement("i");
(r.className = "fa fa-times ab-close-button"),
r.setAttribute("aria-label", "Close Feed"),
r.setAttribute("tabindex", "0"),
r.setAttribute("role", "button");
const a = (t) => {
destroyContentCardsHtml(o), t.stopPropagation();
};
r.addEventListener("keydown", (t) => {
(t.keyCode !== ie.lo && t.keyCode !== ie.Ze) || a(t);
}),
(r.onclick = a);
const i = document.createElement("i");
(i.className = "fa fa-refresh ab-refresh-button"),
t && null == t.lastUpdated && (i.className += " fa-spin"),
i.setAttribute("aria-label", "Refresh Feed"),
i.setAttribute("tabindex", "0"),
i.setAttribute("role", "button");
const l = (e) => {
refreshContentCardsUI(t, o), e.stopPropagation();
};
i.addEventListener("keydown", (t) => {
(t.keyCode !== ie.lo && t.keyCode !== ie.Ze) || l(t);
}),
(i.onclick = l),
s.appendChild(i),
s.appendChild(r),
o.appendChild(generateContentCardsUI(t, e));
const d = () => detectContentCardsImpressions(t, o);
if ((o.addEventListener("scroll", d), !n)) {
window.addEventListener("scroll", d);
const t = P.oe();
(scrollListeners[t] = d), o.setAttribute("data-listener-id", t);
}
return o;
}
export function updateContentCards(t, e, n, o, s) {
if (!D(e)) return;
const r = [];
for (const t of e)
if (t instanceof Card) {
if (t.url && to.test(t.url)) {
const e = eo(t.url);
if (dt(e)) {
E.error(jt(vt.Li, "Content Card"));
continue;
}
}
r.push(t);
}
if (((t.cards = r), (t.lastUpdated = n), null != o))
if ((o.setAttribute("aria-busy", "false"), null == t.lastUpdated))
destroyContentCardsHtml(o);
else {
const e = o.querySelectorAll(".ab-feed-body")[0];
if (null != e) {
const n = generateContentCardsUI(t, s);
e.parentNode && e.parentNode.replaceChild(n, e),
detectContentCardsImpressions(t, n.parentNode);
}
}
}
export function registerContentCardsSubscriptionId(t, e) {
t && e.setAttribute(f, t);
}