if (window.Element && !Element.prototype.closest) {
Element.prototype.closest =
function (s) {
var matches = (this.document || this.ownerDocument).querySelectorAll(s),
i,
el = this;
do {
i = matches.length;
while (--i >= 0 && matches.item(i) !== el) { };
} while ((i < 0) && (el = el.parentElement));
return el;
};
}
(function (w, d) {
var widgetUrl = "https://widget.trustist.com";
var assetUrl = "https://wassets.trustist.com/assets";
var businessKey = "qcx5ae4g";
var locationKey = "3l1ehbs5";
var tenantKey = "";
var tag = "";
var activeWidgets = [];
var accessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbnRpdHlJZCI6IjNsMWVoYnM1IiwiZXhwIjoxNzQwNDA0NzM1LCJpc3MiOiJUcnVzdGlzdCIsImF1ZCI6IldpZGdldHMifQ.mjOR6SfQAYEfWLSFfY4IAZHB0bzUWUiLWm8pCtGL2jM";
var accessTokenExpiry = "1740404735000";
var refreshToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbnRpdHlJZCI6IjNsMWVoYnM1IiwianRpIjoiYzJiOWM5MjgtZjNkNS00MDc1LTkzYTktOGY1NDFlZGEwODI3IiwiZXhwIjoxNzQwNTc2OTM1LCJpc3MiOiJUcnVzdGlzdCIsImF1ZCI6IldpZGdldHMifQ.TZFzxfkf7scOhG_6hdsJYgafqu0k9QI__w7o0Cvswsk";
var template = '
';
var paginator = '';
function start(f) { /in/.test(document.readyState) ? setTimeout(start, 5, f) : f(); }
// add tags
tsAddCssTag(assetUrl + "/css/cleanslate.css");
tsAddCssTag(assetUrl + "/css/reviewlist.css");
w.trustist ??= {};
w.trustist.reviewList = {
draw: function () {
// iterate over all widgets on the page and render
var divs = d.querySelectorAll("[ts-reviewListWidget],div.ts-reviewListWidget");
if (divs.length === 0) {
return;
}
for (var i = 0; i < divs.length; i++) {
tsDisplayWidget(divs[i], tenantKey, businessKey, locationKey);
}
}
};
start(w.trustist.reviewList.draw);
function tsDisplayWidget(target, tenantKey, businessKey, locationKey) {
// get options before cleanslate
var options = tsReadAttributes(target);
// see if the widget requested a different location
var lkey = options.locationKey || locationKey;
var bkey = options.businessKey || businessKey;
var tkey = options.tenantKey || tenantKey;
var tagkey = options.tag || tag;
// set the target's identifiers for later drawing
target.setAttribute("ts-location", lkey);
target.setAttribute("ts-business", bkey);
target.setAttribute("ts-tenant", tkey);
target.setAttribute("ts-tag", tagkey);
// store this widget for later
activeWidgets.push({
locationKey: lkey,
businessKey: bkey,
tenantKey: tkey,
tag: tagkey,
currentPage: 1,
pageSize: options.pageSize,
currentReviewCount: 0,
totalReviewCount: 0
});
// put the container on the page
target.innerHTML = template
.replace("{{font-family}}", options.fontFamily)
.replace("{{color}}", options.color);
// draw summary
var xhr2 = new XMLHttpRequest();
var url = tsBuildSummaryUrl(widgetUrl, tkey, bkey, lkey, tagkey);
xhr2.open("GET", url);
xhr2.onload = function () {
if (xhr2.status === 200 && xhr2.responseText !== "") {
var summary = JSON.parse(xhr2.responseText);
// set the review count on the active widget
tsSetActiveWidgetValue(tenantKey, businessKey, locationKey, tagkey, "totalReviewCount", summary.reviewCount);
// load and draw reviews
tsLoadReviews(target, tenantKey, businessKey, locationKey, tagkey, options);
}
};
xhr2.send();
}
function tsGetActiveWidget(tenantKey, businessKey, locationKey, tag) {
var filtered = activeWidgets.filter(function (o) {
return o.tenantKey === tenantKey && o.businessKey === businessKey && locationKey === locationKey && tag === tag;
});
return filtered[0];
}
function tsSetActiveWidgetValue(tenantKey, businessKey, locationKey, tag, key, value) {
var activeWidget = tsGetActiveWidget(tenantKey, businessKey, locationKey, tag);
activeWidget[key] = value;
}
function tsGetActiveWidgetValue(tenantKey, businessKey, locationKey, tag, key) {
var activeWidget = tsGetActiveWidget(tenantKey, businessKey, locationKey, tag);
return activeWidget[key];
}
function tsAddToActiveWidgetValue(tenantKey, businessKey, locationKey, tag, key, value) {
var activeWidget = tsGetActiveWidget(tenantKey, businessKey, locationKey, tag);
activeWidget[key] += value;
}
function shouldRefreshToken() {
var currentTime = new Date().getTime();
var oneMinuteInMilliseconds = 60000;
return currentTime > (accessTokenExpiry - oneMinuteInMilliseconds);
}
function tsRefreshAccessToken(tenantKey, businessKey, locationKey, callback) {
if (!shouldRefreshToken()) {
callback();
return;
}
var url = widgetUrl + "/refreshToken?refreshToken=" + refreshToken;
if (typeof tenantKey !== "undefined" && tenantKey !== "") url += "&tenantKey=" + tenantKey;
if (typeof businessKey !== "undefined" && businessKey !== "") url += "&businessKey=" + businessKey;
if (typeof locationKey !== "undefined" && locationKey !== "") url += "&locationKey=" + locationKey;
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = function () {
if (xhr.status === 200 && xhr.responseText !== "") {
var json = JSON.parse(xhr.responseText);
accessToken = json.accessToken.accessToken;
accessTokenExpiry = json.accessToken.expiry;
refreshToken = json.refreshToken.accessToken;
}
callback();
};
xhr.send();
}
function tsLoadReviews(target, tenantKey, businessKey, locationKey, tag, options) {
tsRefreshAccessToken(tenantKey, businessKey, locationKey, () => {
var xhr = new XMLHttpRequest();
var currentPage = tsGetActiveWidgetValue(tenantKey, businessKey, locationKey, tag, "currentPage");
var pageSize = tsGetActiveWidgetValue(tenantKey, businessKey, locationKey, tag, "pageSize");
var url = tsBuildUrl(widgetUrl, currentPage, pageSize, tenantKey, businessKey, locationKey, tag, options);
xhr.open("GET", url);
xhr.onload = function () {
if (xhr.status === 200 && xhr.responseText !== "") {
// update local count
var reviews = JSON.parse(xhr.responseText);
tsAddToActiveWidgetValue(tenantKey, businessKey, locationKey, tag, "currentReviewCount", reviews.length);
// draw the reviews
tsDrawReviews(target, reviews, tenantKey, businessKey, locationKey, tag, options);
} else {
}
};
xhr.send();
});
}
function tsBuildUrl(widgetUrl, currentPage, pageSize, tenantKey, businessKey, locationKey, tag, options) {
var url = widgetUrl + "/reviewlistdata?v=1&accessToken=" + accessToken + "&pageNum=" + currentPage + "&pageSize=" + pageSize;
if (typeof tenantKey !== "undefined" && tenantKey !== "") url += "&tenantKey=" + tenantKey;
if (typeof businessKey !== "undefined" && businessKey !== "") url += "&businessKey=" + businessKey;
if (typeof locationKey !== "undefined" && locationKey !== "") url += "&locationKey=" + locationKey;
if (typeof tag !== "undefined" && tag !== "") url += "&tag=" + tag;
if (options.ratingsAbove > 0) url += "&ratingFrom=" + options.ratingsAbove;
if (options.exclude > '') url += "&exclude=" + options.exclude;
if (options.displayFullName) url += "&displayFullName=true";
if (options.displayAdditionalData) url += "&includeAdditionalData=true";
return url;
}
function tsBuildSummaryUrl(widgetUrl, tkey, bkey, lkey, tagkey) {
var url = widgetUrl + "/reviewsummary?";
if (typeof tkey !== "undefined" && tkey !== "") url += "&tenantKey=" + tkey;
if (typeof bkey !== "undefined" && bkey !== "") url += "&businessKey=" + bkey;
if (typeof lkey !== "undefined" && lkey !== "") url += "&locationKey=" + lkey;
if (typeof tagkey !== "undefined" && tagkey !== "") url += "&tag=" + tagkey;
return url;
}
function tsDrawReviews(target, reviews, tenantKey, businessKey, locationKey, tag, options) {
var reviewContent = "";
var totalReviews = tsGetActiveWidgetValue(tenantKey, businessKey, locationKey, tag, "totalReviewCount");
var currentReviews = tsGetActiveWidgetValue(tenantKey, businessKey, locationKey, tag, "currentReviewCount");
var btnSubmit;
reviews.forEach(function (review) {
reviewContent += tsRenderReview(review, options)
.replace(new RegExp("{{font-family}}", "g"), options.fontFamily)
.replace(new RegExp("{{color}}", "g"), options.color);
});
// add the reviews to the page but retain the comment for additional reviews to be added later
target.innerHTML = target.innerHTML.replace("", reviewContent + "");
if (currentReviews < totalReviews) {
if (target.innerHTML.indexOf("") > 0) {
// add the paginator if it doesn't already exist
target.innerHTML = target.innerHTML.replace("", paginator);
// now hook up to the event
btnSubmit = target.querySelector("#tsLoadMore");
btnSubmit.setAttribute("ts-location", locationKey);
btnSubmit.setAttribute("ts-business", businessKey);
btnSubmit.setAttribute("ts-tenant", tenantKey);
btnSubmit.setAttribute("ts-tag", tag);
btnSubmit.addEventListener("click", tsLoadMore);
} else {
// still more reviews to show so reenable the show more button
btnSubmit = target.querySelector("#tsLoadMore");
btnSubmit.addEventListener("click", tsLoadMore); // reconnect the disconnected event listener
btnSubmit.disabled = false;
}
} else {
// shown all the reviews, remove the button
btnSubmit = target.querySelector("#tsLoadMore");
if (btnSubmit) {
btnSubmit.style.setProperty("display", "none", "important");
}
}
}
function tsLoadMore(evnt) {
// scoped to the button
evnt.preventDefault();
this.disabled = true;
var tenant = this.getAttribute("ts-tenant");
var business = this.getAttribute("ts-business");
var location = this.getAttribute("ts-location");
var tag = this.getAttribute("ts-tag");
var target = this.closest("[ts-reviewlistwidget],div.ts-reviewListWidget");
var options = tsReadAttributes(target);
tsAddToActiveWidgetValue(tenant, business, location, tag, "currentPage", 1);
tsLoadReviews(target, tenant, business, location, tag, options);
}
function tsRenderReview(review, options) {
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
var d = new Date(review.datePublished);
var curr_date = d.getDate();
var curr_month = d.getMonth(); //Months are zero based
var curr_year = d.getFullYear();
var dateString = curr_date + " " + months[curr_month] + " " + curr_year;
var reviewContent = review.reviewBody || "";
var reviewBy = "Customer Review";
var reviewDate = "";
var reviewReply = "";
var truncateLength = Number(options.truncateLength);
var reviewId = review.datePublished.replace(new RegExp(":", "g"), "-");
if (isNaN(truncateLength) === false && truncateLength > 0 && reviewContent.length > truncateLength) {
reviewContent = reviewContent.substr(0, truncateLength) +
'... read more' +
'' +
reviewContent.substr(truncateLength, reviewContent.length - truncateLength) + '';
}
if (options.showLocation) {
reviewBy += " for " + review.subject;
}
if (options.suppressReviewNames !== "true") {
reviewBy += " by " + review.author.name;
}
if (options.suppressReviewNames !== "true" && options.suppressReviewDates !== "true") {
reviewDate = " left on " + dateString;
}
var reviewLine1 = options.suppressTitle === "false" ? reviewBy + reviewDate : "";
if (review.reply && review.reply !== "") {
var replyText = "Reply";
if (options.suppressReviewDates !== "true") {
var replyDate = new Date(review.replyDate);
var replyDateString = replyDate.getDate() + " " + months[replyDate.getMonth()] + " " + replyDate.getFullYear();
replyText += " left " + replyDateString;
}
reviewReply = '' + replyText + ': ' + review.reply + '';
}
var verified = '';
if (options.suppressVerified === "false" && review["@type"].toUpperCase() === "9A9B0D66-E568-474D-939B-F1859A3769D9") { // review.verified &&
verified = ' Verified Review';
}
var reply = '';
var content = '';
var answers = '';
if (options.displayAdditionalData && review.answers) {
for (i = 0; i < review.answers.length; i++) {
answers += '