/* global wccomCurrentProduct */
( function( global ) {
// Global var for throttling.
var throttleWait = false;
function trackIt( name, parameters ) {
var wccom = global.wccom || {};
var tracks = wccom.fireTracksEvent || function() {};
// eslint-disable-next-line camelcase
var product_id = JSON.parse( wccomCurrentProduct ).productId || '';
// eslint-disable-next-line camelcase
parameters.product_id = product_id;
tracks( name, parameters );
}
function trackRatingClick( event ) {
var starRating = event.currentTarget.getAttribute( 'for' ).slice( -1 );
trackIt( 'product_review_rating_click', { stars: starRating } );
}
function trackRatingSubmit() {
trackIt( 'product_review_rating_submit', {} );
}
function viewingReviews() {
var reviewsContainer = document.getElementById( 'reviews' );
// Check if we already tracked this view.
if (
null === reviewsContainer ||
reviewsContainer.classList.contains( 'tracks-tracked' )
) {
return;
}
// A buffer to ensure the container is well into view.
var reviewContainerBuffer = 150;
// get window height
var windowHeight = window.innerHeight;
// get number of pixels that the document is scrolled
var scrollY = window.scrollY || window.pageYOffset;
// get current scroll position
// (distance from the top of the page to the bottom of the current viewport)
var scrollPosition = scrollY + windowHeight;
// get element position (distance from the top of the page to the bottom of the element)
var elementPosition =
reviewsContainer.getBoundingClientRect().top + scrollY + reviewContainerBuffer;
// is scroll position greater than element position? (is element in view?)
if ( scrollPosition > elementPosition ) {
reviewsContainer.classList.add( 'tracks-tracked' );
return true;
}
return false;
}
function maybeTrackReviewsView() {
if ( viewingReviews() ) {
trackIt( 'product_reviews_viewed', {} );
// Once we tracked the view we can remove the event listener.
document.removeEventListener( 'scroll', throttledMaybeTrackReviewsView );
}
}
function trackSortReviews() {
var e = document.querySelector( '.wccom-product-ratings__sort-container select' );
trackIt( 'product_reviews_sort_reviews', { sort: e.options[ e.selectedIndex ].text } );
}
function trackReviewVoteUp( event ) {
var targetElement = event.target || event.srcElement;
var properties = {};
if ( 'undefined' !== typeof targetElement.dataset.commentId ) {
// eslint-disable-next-line camelcase
properties.comment_id = targetElement.dataset.commentId;
}
trackIt( 'product_review_vote_up', properties );
}
function trackReviewVoteDown( event ) {
var targetElement = event.target || event.srcElement;
var properties = {};
if ( 'undefined' !== typeof targetElement.dataset.commentId ) {
// eslint-disable-next-line camelcase
properties.comment_id = targetElement.dataset.commentId;
}
trackIt( 'product_review_vote_down', properties );
}
function trackReviewVoteClickListener( event ) {
if ( event.target.classList.contains( 'vote-up' ) ) {
trackReviewVoteUp( event );
}
if ( event.target.classList.contains( 'vote-down' ) ) {
trackReviewVoteDown( event );
}
}
/*
* A throttle function to avoid calling scroll event 100's of times in a second,
* lodash has a throttle, but is only available via react and not vanilla js.
*/
function throttle( callback, limit ) {
// If we're not waiting
if ( ! throttleWait ) {
// Execute users function
callback();
// Prevent future invocations
throttleWait = true;
// After a period of time
window.setTimeout( function() {
// And allow future invocations
throttleWait = false;
}, limit );
}
}
function throttledMaybeTrackReviewsView() {
throttle( maybeTrackReviewsView, 1000 );
}
function init() {
Array.prototype.slice.call(
document.querySelectorAll( 'label[for^="review_rating_"]' ),
).forEach( function( star ) {
star.addEventListener( 'click', trackRatingClick );
} );
var submit = document
.querySelector( '.form-contribution button[type="submit"]' );
if ( submit ) {
submit.addEventListener( 'click', trackRatingSubmit );
}
// Track onchange for the sorting dropdown.
const ratingSortMethod = document.querySelector(
'.wccom-product-ratings__sort-container .select',
);
if ( ratingSortMethod ) {
ratingSortMethod.addEventListener( 'change', trackSortReviews );
}
// Since reviews are ajax loaded and there is no js event triggered
// we use a general click listener on window and then check in the function the class.
window.addEventListener( 'click', trackReviewVoteClickListener );
}
document.addEventListener( 'DOMContentLoaded', init );
document.addEventListener( 'scroll', throttledMaybeTrackReviewsView );
}( this ) );
;
/* global MutationObserver */
( function() {
var observer;
function starChange( event ) {
var starRating = parseInt(
event.currentTarget.getAttribute( 'for' ).slice( -1 ),
10
);
openForm( starRating );
}
function getCurrentRating() {
const ratingInput = document.querySelector(
'#review_rating_field .input-checkbox:checked'
);
if ( ratingInput ) {
return ratingInput.value;
}
return 0;
}
function openSubmissionForm() {
openForm( getCurrentRating() );
}
/**
* When the submit review form opens it fetches the existing review
* and updates form data with the current review state.
*
* We want to force the selected rating value and to do this,
* we listen to changes on #review_attachment_type_field
* and update the rating with the selected value.
*
* We use #review_attachment_type_field because it get's updated after rating is updated.
* For reference see: wc-product-reviews-pro-frontend.min.js
*
* @param {number} starRating Clicked rating value.
*/
function forceClickedRatingToBeActive( starRating ) {
if ( observer ) {
observer.disconnect();
}
var ratingFieldset = document.getElementById( 'review_attachment_type_field' );
if ( ratingFieldset ) {
var config = { attributes: true };
observer = new MutationObserver(
function() {
const starRatingLabel = document.querySelector(
`#review_rating_${
starRating
}:not(:checked) ~ label.checkbox[for="review_rating_${
starRating
}"]`
);
if ( starRatingLabel ) {
starRatingLabel.click();
}
}
);
observer.observe( ratingFieldset, config );
}
}
function openForm( starRating ) {
if ( starRating ) {
forceClickedRatingToBeActive( starRating );
}
document.getElementById( 'wccom-extension-review__more' )
.removeAttribute( 'hidden' );
document.getElementById( 'review_comment_field' )
.style.display = 'block';
}
function cancelReview( event ) {
event.preventDefault();
document.getElementById( 'wccom-extension-review__more' )
.setAttribute( 'hidden', '' );
}
function init() {
if ( ! document.getElementById( 'wccom-extension-review__more' ) ) {
return;
}
Array.prototype.slice.call(
document.querySelectorAll( 'label[for^="review_rating_"]' )
).forEach( function( star ) {
star.addEventListener( 'click', starChange );
} );
document.getElementById( 'wccom-extension-review__cancel' )
.addEventListener( 'click', cancelReview );
document
.getElementById( 'review_comment_field' )
.classList
.remove( 'validate-required' );
Array.prototype.slice.call(
document.querySelectorAll( '#reviews .edit-comment' )
).forEach( function( editButton ) {
editButton.addEventListener( 'click', openSubmissionForm );
} );
}
document.addEventListener( 'DOMContentLoaded', init );
}() );
;