: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
/* eslint-disable camelcase */
/* global flatpickr, Chart, moment, ajaxurl, wpforms_admin_payments_overview, wpforms_admin */
* Script for manipulating DOM events in the "Payments Overview" page.
* This script will be accessible in the "WPForms" → "Payments" page.
const WPFormsPaymentsOverview = window.WPFormsPaymentsOverview || ( function( document, window, $, ajaxurl, l10n ) {
* The ISO 639-2 language code of the WordPress installation.
* Get the base currency code.
* Get the number of decimal points for the currency.
currencyDecimals: l10n.decimals,
* Cryptographic token for validating authorized Ajax data exchange.
* Initial dataset that will appear on the chart.
* Chart type. Options are "Line" or "Bar".
* A line chart is a way of plotting data points on a line.
* A bar chart provides a way of showing data values represented as vertical bars.
type: l10n.settings.graph_style === 1 ? 'bar' : 'line',
* Timespan (date range) delimiter. By default: ' - '.
delimiter: l10n.delimiter,
* The Moment.js compatible format string to use for the tooltip.
tooltipFormat: l10n.date_format,
* @return {URL} The current page URI.
// eslint-disable-next-line compat/compat
return new URL( l10n.page_uri );
* Generic CSS class names for applying visual changes.
calculated: 'is-calculated',
* Report stats that are currently being viewed.
report: l10n.active_report,
* Whether the viewed stats are representing the price amounts.
* @return {Object} Colors object specified for the graph.
const isLine = this.type === 'line';
total_payments: { // Bahama Blue.
hoverBorderColor: '#055f9a',
hoverBackgroundColor: '#055f9a',
backgroundColor: isLine ? '#e6f0f7' : '#056aab',
total_sales: { // Fun Green.
hoverBorderColor: '#00831e',
hoverBackgroundColor: '#00831e',
backgroundColor: isLine ? '#e3f3e4' : '#008a20',
total_refunded: { // Bright Gray.
hoverBorderColor: '#373e45',
hoverBackgroundColor: '#373e45',
backgroundColor: isLine ? '#ebebec' : '#50575e',
default: { // Zest - WPForms.
hoverBorderColor: '#cd6622',
hoverBackgroundColor: '#cd6622',
backgroundColor: isLine ? '#fcf1ea' : '#e27730',
* @return {Object} Localized strings.
* In case the time span extends to other years, the xAxes date display format is updated to include the year identifier.
* @return {Object} Localized strings.
get xAxesDisplayFormat() {
if ( ! this.timespan.length ) {
const dates = this.timespan.split( this.delimiter );
if ( ! Array.isArray( dates ) || dates.length !== 2 ) {
const startYear = moment( dates[ 0 ] ).format( 'YYYY' );
const endYear = moment( dates[ 1 ] ).format( 'YYYY' );
return startYear === endYear ? 'MMM D' : 'MMM D YYYY';
* Returns language-sensitive number formatting instance.
* @return {Object} Returns a new NumberFormat object.
return new Intl.NumberFormat( this.locale, {
currencyDisplay: 'narrowSymbol',
minimumFractionDigits: this.currencyDecimals,
maximumFractionDigits: this.currencyDecimals,
* Retrieves the previewed dataset label.
* @return {string} The dataset tooltip label.
const $statcard = $( `[data-stats=${ this.report }]` );
if ( ! $statcard.length ) {
return $statcard.find( '.statcard-label' ).text();
* @return {Object} Scriptable options as a function which is called for the chart instances.
get settings() { /* eslint max-lines-per-function: ["error", 200] */
pointBackgroundColor: '#ffffff',
...( this.colors[ this.report ] || this.colors.default ),
offset: this.type === 'bar',
tooltipFormat: this.tooltipFormat,
day: this.xAxesDisplayFormat,
reverse: $( 'body' ).hasClass( 'rtl' ),
callback( value, index, values ) {
// Distribute the ticks equally starting from the right side of xAxis.
const gap = Math.floor( values.length / 7 );
if ( ( values.length - index - 1 ) % gap === 0 ) {
// Update the scales if the dataset returned includes price amounts.
return this.amountFormatter.format( value );
// Make sure the tick value has no decimals.
if ( Math.floor( value ) === value ) {
label: ( { yLabel: value } ) => {
let label = `${ this.datasetLabel } `;
// Update the scales if the dataset returned includes price amounts.
label += this.amountFormatter.format( value );
responsiveAnimationDuration: 0,
maintainAspectRatio: false,
* Public functions and properties.
* Setup. Prepare some variables.
el.$document = $( document );
el.$wrapper = $( '.wpforms-payments-wrap-payments' );
el.$form = $( '#wpforms-payments-table' );
el.$spinner = $( '.wpforms-overview-chart .spinner' );
el.$canvas = $( '#wpforms-payments-overview-canvas' );
el.$filterBtn = $( '#wpforms-datepicker-popover-button' );
el.$datepicker = $( '#wpforms-payments-overview-datepicker' );
el.$filterForm = $( '.wpforms-overview-top-bar-filter-form' );
el.$activeStat = el.$filterForm.find( 'input[name="statcard"]' );
el.$table = $( '.wpforms-table-list' );
el.$notice = $( '.wpforms-overview-chart-notice' );
el.$reports = $( '.wpforms-payments-overview-reports' );
el.$multiSelect = $( '.wpforms-multiselect' );
.on( 'click', { selectors: [ '.wpforms-datepicker-popover', '.wpforms-dash-widget-settings-menu' ] }, app.handleOnClickOutside );
.on( 'submit', '.wpforms-overview-top-bar-filter-form', app.handleOnSubmitDatepicker )
.on( 'submit', '#wpforms-payments-table', app.handleOnSubmitOverviewTable )
.on( 'click', '#doaction', app.handleOnBulkAction )
.on( 'click', '.wpforms-overview-top-bar-filter-form [type="reset"]', app.handleOnResetDatepicker )
.on( 'change', '.wpforms-overview-top-bar-filter-form [type="radio"]', app.handleOnUpdateDatepicker )
.on( 'click', '.wpforms-payments-overview-reports button', app.handleOnChangeStatCard )
.on( 'click', '.wpforms-dash-widget-settings-menu-save', app.handleOnSaveSettings )
.on( 'click', '#wpforms-payments-mode-toggle', app.handleOnToggleMode )
.on( 'click', '#wpforms-dash-widget-settings-button', { selector: '.wpforms-dash-widget-settings-menu', hide: '.wpforms-datepicker-popover' }, app.handleOnToggle )
.on( 'click', '#wpforms-datepicker-popover-button', { selector: '.wpforms-datepicker-popover', hide: '.wpforms-dash-widget-settings-menu' }, app.handleOnToggle );
* Create an instance of "flatpickr".
if ( ! el.$datepicker.length ) {
vars.timespan = el.$datepicker.val();
vars.datepicker = flatpickr( el.$datepicker, {
// Localized per-instance, if applicable.
...flatpickr.l10ns[ vars.locale ] || {},
rangeSeparator: vars.delimiter,
onChange( selectedDates, dateStr, instance ) {
// Immediately after a user interacts with the datepicker, ensure that the "Custom" option is chosen.
const $custom = el.$filterForm.find( 'input[value="custom"]' );
$custom.prop( 'checked', true );
app.selectDatepickerChoice( $custom.parent() );