Skip to content

Instantly share code, notes, and snippets.

@nativerez
Created February 23, 2022 18:10
Show Gist options
  • Save nativerez/a06188fab64345ebd1e95b4ca66587e7 to your computer and use it in GitHub Desktop.
Save nativerez/a06188fab64345ebd1e95b4ca66587e7 to your computer and use it in GitHub Desktop.
(function ($) {
$.fn.googlePlaces = function (options) {
// This is the easiest way to have default options.
var settings = $.extend({
// These are the defaults.
header: "Google Reviews",
footer: '',
maxRows: 6,
minRating: 4,
months: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
textBreakLength: "40",
shortenNames: true,
placeId: "",
moreReviewsButtonUrl: '',
moreReviewsButtonLabel: 'Show More Reviews',
writeReviewButtonUrl: '',
writeReviewButtonLabel: 'Write New Review',
showReviewDate: false
}, options);
var targetDiv = this[0];
var targetDivJquery = this;
var renderMoreReviewsButton = function () {
return '<div class="mt-4 more-reviews"><a class="text-green-800 hover:underline" href="' + settings.moreReviewsButtonUrl + '" target="_blank">' + settings.moreReviewsButtonLabel + '</a></div>';
};
var renderWriteReviewButton = function () {
return '<div class="write-review"><a href="' + settings.writeReviewButtonUrl + '" target="_blank">' + settings.writeReviewButtonLabel + '</a></div>';
};
var renderHeader = function (header) {
var html = '<h1 class="text-3xl lg:text-5xl">' + header + '</h1>';
targetDivJquery.append(html);
};
var renderFooter = function (footer) {
var html = "";
var htmlButtons = "";
if (settings.moreReviewsButtonUrl) {
htmlButtons += renderMoreReviewsButton();
}
if (settings.writeReviewButtonUrl) {
htmlButtons += renderWriteReviewButton();
}
if (htmlButtons != "") {
html += '<div class="buttons d-flex justify-content-center">' + htmlButtons + '</div>';
}
html += "" + footer + "";
targetDivJquery.after(html);
};
var shortenName = function (name) {
if (name.split(" ").length > 1) {
var shortenedName = "";
shortenedName = name.split(" ");
var lastNameFirstLetter = shortenedName[1][0];
var firstName = shortenedName[0];
if (lastNameFirstLetter == ".") {
return firstName;
} else {
return firstName + " " + lastNameFirstLetter + ".";
}
} else if (name != undefined) {
return name;
} else {
return '';
}
};
var renderStars = function (rating) {
var stars = '<div class="review-stars"><ul class="flex items-center mt-2 mb-4 space-x-2">';
// fills gold stars
for (var i = 0; i < rating; i++) {
stars += '<li><svg class="w-4 h-4 fill-current text-yellow-500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z"/></svg></li>';
}
// fills empty stars
if (rating < 5) {
for (var i = 0; i < (5 - rating); i++) {
stars += '<li><svg class="w-4 h-4 fill-current text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10 15l-5.878 3.09 1.123-6.545L.489 6.91l6.572-.955L10 0l2.939 5.955 6.572.955-4.756 4.635 1.123 6.545z"/></svg></li>';
}
}
stars += "</ul></div>";
return stars;
};
var convertTime = function (UNIX_timestamp) {
var newDate = new Date(UNIX_timestamp * 1000);
var months = settings.months;
var time = newDate.getDate() + ". " + months[newDate.getMonth()] + " " + newDate.getFullYear();
return time;
};
var filterReviewsByMinRating = function (reviews) {
if (reviews === void 0) {
return [];
} else {
for (var i = reviews.length - 1; i >= 0; i--) {
var review = reviews[i];
if (review.rating < settings.minRating) {
reviews.splice(i, 1);
}
}
return reviews;
}
};
var sortReviewsByDateDesc = function (reviews) {
if (typeof reviews != "undefined" && reviews != null && reviews.length != null && reviews.length > 0) {
return reviews.sort(function (a, b) { return (a.time > b.time) ? 1 : ((b.time > a.time) ? -1 : 0); }).reverse();
} else {
return []
}
}
var renderReviews = function (reviews) {
reviews.reverse();
var html = "";
var rowCount = (settings.maxRows > 0) ? settings.maxRows - 1 : reviews.length - 1;
rowCount = (rowCount > reviews.length - 1) ? reviews.length - 1 : rowCount;
for (var i = rowCount; i >= 0; i--) {
var review = reviews[i];
var stars = renderStars(review.rating);
var date = convertTime(review.time);
var name = settings.shortenNames ? shortenName(review.author_name) : review.author_name;
var style = (review.text.length > parseInt(settings.textBreakLength)) ? "'review-item-long bg-white border border-gray-300 p-6 rounded'" : "'review-item bg-white border border-gray-300 p-6 rounded'";
html = html + "<div class=" + style + "><div class='review-meta'>" + "<p class='review-date'>"+ date +"</p>" + "<span class='review-author text-xl'>" + name + "</span><span class='review-sep'></span>" + "</div>" + stars + "<p class='review-text text-gray-700'>" + review.text + "</p></div>";
// I do not need to display the date... but if you do:
}
targetDivJquery.append(html);
};
// GOOGLE PLACES API CALL STARTS HERE
// initiate a Google Places Object
var service = new google.maps.places.PlacesService(targetDiv);
// set.getDetails takes 2 arguments: request, callback
// see documentation here: https://developers.google.com/maps/documentation/javascript/3.exp/reference#PlacesService
const request = {
placeId: settings.placeId
};
// the callback is what initiates the rendering if Status returns OK
var callback = function (place, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
var filteredReviews = filterReviewsByMinRating(place.reviews);
var sortedReviews = sortReviewsByDateDesc(filteredReviews);
if (sortedReviews.length > 0) {
renderHeader(settings.header);
renderReviews(sortedReviews);
renderFooter(settings.footer);
}
}
}
return this.each(function () {
// Runs the Plugin
if (settings.placeId === undefined || settings.placeId === "") {
console.error("NO PLACE ID DEFINED");
return
}
service.getDetails(request, callback);
});
};
}(jQuery));
$(document).ready(function () {
if ($("#google-reviews").length == 0) {
return
}
//Find a placeID via https://developers.google.com/places/place-id
$("#google-reviews").googlePlaces({
placeId: 'ChIJGxux84qte0gR0XXuMn0OhP4',
maxRows: 12,
moreReviewsButtonUrl: 'https://www.google.com/search?q=baskehouse+32&sxsrf=AOaemvIWBb7BrqTo31rPk0ULoFz5wJEx-A%3A1641908978967&ei=8ordYcC8Oov2gAbH6rzQBw&ved=0ahUKEwjA_cbL66n1AhULO8AKHUc1D3oQ4dUDCA4&uact=5&oq=baskehouse+32&gs_lcp=Cgdnd3Mtd2l6EAMyCgguEMcBEK8BEA0yBAgAEA0yBAgAEA0yBggAEA0QHjIICAAQCBANEB4yCAgAEAgQDRAeOgQIIxAnOgsILhDHARCvARCRAjoLCAAQgAQQsQMQgwE6DgguEIAEELEDEMcBEKMCOgQILhBDOgQIABBDOgUIABCRAjoKCC4QxwEQowIQQzoKCC4QxwEQ0QMQQzoICC4QgAQQsQM6BwgAEMkDEEM6CgguEMcBEK8BEEM6DgguEIAEELEDEMcBEK8BOggIABCABBCxAzoFCAAQgAQ6DQguELEDEMcBEKMCEEM6BwgAELEDEEM6CAgAEIAEEMkDOgcILhCxAxAKOgcIABCxAxAKOgQIABAKOgcIABDJAxAKOgoILhDHARCvARAKOgUIABCSAzoICAAQBRAKEB5KBAhBGABKBAhGGABQAFibEGC9EWgAcAB4AIABgQGIAbEJkgEDOS40mAEAoAEBwAEB&sclient=gws-wiz#lrd=0x487bad8af3b11b1b:0xfe840e7d32ee75d1,1,,,', // url to Google Place reviews popup
minRating: 4, // minimum rating of reviews to be displayed
header: 'Latest from our customers', // html/text over Reviews
footer: ' ', // html/text under Reviews block
shortenNames: true
});
});
// Navbar Toggle
document.addEventListener('DOMContentLoaded', function () {
// Get all "navbar-burger" elements
var $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
// Check if there are any navbar burgers
if ($navbarBurgers.length > 0) {
// Add a click event on each of them
$navbarBurgers.forEach(function ($el) {
$el.addEventListener('click', function () {
// Get the "main-nav" element
var $target = document.getElementById('main-nav');
// Toggle the class on "main-nav"
$target.classList.toggle('hidden');
});
});
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment