@braze/web-sdk
Version:
Braze SDK for web sites and other JS platforms.
212 lines (211 loc) • 7.1 kB
JavaScript
import rr from "./base-feed.js";
import {
getCardId as be,
markCardAsRead as ye,
} from "../Card/display/card-display.js";
import { bottomIsInView as B, topIsInView as x } from "../util/dom-utils.js";
import { Card, ControlCard } from "../Card/index.js";
import { cardToHtml as Fe } from "../Card/display/card-display.js";
import { isArray as z } from "../util/code-utils.js";
import { KeyCodes as mt } from "../util/key-codes.js";
import ge from "../l10n/l10n-manager-factory.js";
import { removeSubscription } from "../Core/remove-subscription.js";
import { logger as N, Guid as G } 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 jt,
ineligibleBrazeActionURLErrorMessage as dt,
getDecodedBrazeAction as eo,
containsUnknownBrazeAction as ft,
} from "../util/braze-actions.js";
import {
bottomHadImpression as xe,
impressOnBottom as j,
impressOnTop as $,
topHadImpression as Ee,
} from "./detect-impression.js";
import { SUBSCRIPTION_ID_DATA_ATTRIBUTE as f } from "./constants.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 destroyFeedHtml(e) {
e &&
((e.className = e.className.replace("ab-show", "ab-hide")),
setTimeout(() => {
e && e.parentNode && e.parentNode.removeChild(e);
}, rr.Ih));
const t = e.getAttribute(f);
null != t && removeSubscription(t);
const o = e.getAttribute("data-listener-id");
null != o &&
(window.removeEventListener("scroll", scrollListeners[o]),
delete scrollListeners[o]);
}
export function generateFeedBody(e, t) {
const o = ge.ea(),
s = document.createElement("div");
if (
((s.className = "ab-feed-body"),
s.setAttribute("aria-label", "Feed"),
s.setAttribute("role", "feed"),
null == e.lastUpdated)
) {
const e = document.createElement("div");
e.className = "ab-no-cards-message";
const t = document.createElement("i");
(t.className = "fa fa-spinner fa-spin fa-4x ab-initial-spinner"),
e.appendChild(t),
s.appendChild(e);
} else {
let n = !1;
const logCardClick = (t) => e.logCardClick(t);
for (const r of e.cards) {
const i = r instanceof ControlCard;
!i || e.nr()
? (s.appendChild(Fe(r, logCardClick, t, o.Oo())), (n = n || !i))
: N.error(
"Received a control card for a legacy news feed. Control cards are only supported with content cards.",
);
}
if (!n) {
const e = document.createElement("div");
(e.className = "ab-no-cards-message"),
(e.innerHTML = o.get("NO_CARDS_MESSAGE") || ""),
e.setAttribute("role", "article"),
s.appendChild(e);
}
}
return s;
}
export function detectFeedImpressions(e, t) {
if (null != e && null != t) {
const o = [],
s = t.querySelectorAll(".ab-card");
e._o || (e._o = {});
for (let t = 0; t < s.length; t++) {
const n = be(s[t]),
r = x(s[t]),
i = B(s[t]);
if (e._o[n]) {
r || i || ye(s[t]);
continue;
}
let a = Ee(s[t]),
d = xe(s[t]);
const l = a,
c = d;
if (
(!a && r && ((a = !0), $(s[t])), !d && i && ((d = !0), j(s[t])), a && d)
) {
if (l && c) continue;
for (const t of e.cards)
if (t.id === n) {
(e._o[t.id] = !0), o.push(t);
break;
}
}
}
o.length > 0 && e.logCardImpressions(o);
}
}
export function refreshFeed(e, t) {
if (null == e || null == t) return;
t.setAttribute("aria-busy", "true");
const o = t.querySelectorAll(".ab-refresh-button")[0];
null != o && (o.className += " fa-spin");
const s = new Date().valueOf().toString();
t.setAttribute("data-last-requested-refresh", s),
setTimeout(() => {
if (t.getAttribute("data-last-requested-refresh") === s) {
const e = t.querySelectorAll(".fa-spin");
for (let t = 0; t < e.length; t++)
e[t].className = e[t].className.replace(/fa-spin/g, "");
const o = t.querySelectorAll(".ab-initial-spinner")[0];
if (null != o) {
const e = document.createElement("span");
(e.innerHTML = ge.ea().get("FEED_TIMEOUT_MESSAGE") || ""),
null != o.parentNode &&
(o.parentNode.appendChild(e), o.parentNode.removeChild(o));
}
"true" === t.getAttribute("aria-busy") &&
t.setAttribute("aria-busy", "false");
}
}, rr.Ro),
e.sr();
}
export function feedToHtml(e, t, o) {
const s = document.createElement("div");
(s.className = "ab-feed ab-hide ab-effect-slide"),
s.setAttribute("role", "dialog"),
s.setAttribute("aria-label", "Feed"),
s.setAttribute("tabindex", "-1");
const n = document.createElement("div");
(n.className = "ab-feed-buttons-wrapper"),
n.setAttribute("role", "group"),
s.appendChild(n);
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 i = (e) => {
destroyFeedHtml(s), e.stopPropagation();
};
r.addEventListener("keydown", (e) => {
(e.keyCode !== mt.Wo && e.keyCode !== mt.Xo) || i(e);
}),
(r.onclick = i);
const a = document.createElement("i");
(a.className = "fa fa-refresh ab-refresh-button"),
e && null == e.lastUpdated && (a.className += " fa-spin"),
a.setAttribute("aria-label", "Refresh Feed"),
a.setAttribute("tabindex", "0"),
a.setAttribute("role", "button");
const d = (t) => {
refreshFeed(e, s), t.stopPropagation();
};
a.addEventListener("keydown", (e) => {
(e.keyCode !== mt.Wo && e.keyCode !== mt.Xo) || d(e);
}),
(a.onclick = d),
n.appendChild(a),
n.appendChild(r),
s.appendChild(generateFeedBody(e, t));
const l = () => detectFeedImpressions(e, s);
if ((s.addEventListener("scroll", l), !o)) {
window.addEventListener("scroll", l);
const e = G.ce();
(scrollListeners[e] = l), s.setAttribute("data-listener-id", e);
}
return s;
}
export function updateFeedCards(e, t, o, s, n) {
if (!z(t)) return;
const r = [];
for (const e of t)
if (e instanceof Card) {
if (e.url && to.test(e.url)) {
const t = eo(e.url);
if (ft(t)) {
N.error(dt(jt.Tr, "Content Card"));
continue;
}
}
r.push(e);
}
if (((e.cards = r), (e.lastUpdated = o), null != s))
if ((s.setAttribute("aria-busy", "false"), null == e.lastUpdated))
destroyFeedHtml(s);
else {
const t = s.querySelectorAll(".ab-feed-body")[0];
if (null != t) {
const o = generateFeedBody(e, n);
t.parentNode && t.parentNode.replaceChild(o, t),
detectFeedImpressions(e, o.parentNode);
}
}
}
export function registerFeedSubscriptionId(e, t) {
e && t.setAttribute(f, e);
}