Sets an element to show the time remaining until a given instant.
Expects HTML like:
<div></div>
Provide inline configuration like:
<div data-countdown="name: 'value'"></div>@module Countdown @augments JQPlugin @example $(selector).countdown({until: +300}) */ $.JQPlugin.createPlugin({ /** The name of the plugin. */ name: pluginName, /** Countdown expiry callback. Triggered when the countdown expires. @callback expiryCallback */ /** Countdown server synchronisation callback. Triggered when the countdown is initialised. @callback serverSyncCallback @return {Date} The current date/time on the server as expressed in the local timezone. */ /** Countdown tick callback. Triggered on every
tickInterval
ticks of the countdown.
@callback tickCallback
@param periods {number[]} The breakdown by period (years, months, weeks, days,
hours, minutes, seconds) of the time remaining/passed. */
/** Countdown which labels callback.
Triggered when the countdown is being display to determine which set of labels
(labels
, labels1
, ...) are to be used for the current period value.
@callback whichLabelsCallback
@param num {number} The current period value.
@return {number} The suffix for the label set to use. */
/** Default settings for the plugin.
@property until {Date|number|string} The date/time to count down to, or number of seconds
offset from now, or string of amounts and units for offset(s) from now:
'Y' years, 'O' months, 'W' weeks, 'D' days, 'H' hours, 'M' minutes, 'S' seconds.
@example until: new Date(2013, 12-1, 25, 13, 30)
until: +300
until: '+1O -2D'
@property [since] {Date|number|string} The date/time to count up from, or
number of seconds offset from now, or string for unit offset(s):
'Y' years, 'O' months, 'W' weeks, 'D' days, 'H' hours, 'M' minutes, 'S' seconds.
@example since: new Date(2013, 1-1, 1)
since: -300
since: '-1O +2D'
@property [timezone=null] {number} The timezone (hours or minutes from GMT) for the target times,
or null for client local timezone.
@example timezone: +10
timezone: -60
@property [serverSync=null] {serverSyncCallback} A function to retrieve the current server time
for synchronisation.
@property [format='dHMS'] {string} The format for display - upper case for always, lower case only if non-zero,
'Y' years, 'O' months, 'W' weeks, 'D' days, 'H' hours, 'M' minutes, 'S' seconds.
@property [layout=''] {string} Build your own layout for the countdown.
@example layout: '{d<}{dn} {dl}{d>} {hnn}:{mnn}:{snn}'
@property [compact=false] {boolean} True to display in a compact format, false for an expanded one.
@property [padZeroes=false] {boolean} True to add leading zeroes
@property [significant=0] {number} The number of periods with non-zero values to show, zero for all.
@property [description=''] {string} The description displayed for the countdown.
@property [expiryUrl=''] {string} A URL to load upon expiry, replacing the current page.
@property [expiryText=''] {string} Text to display upon expiry, replacing the countdown. This may be HTML.
@property [alwaysExpire=false] {boolean} True to trigger onExpiry
even if target time has passed.
@property [onExpiry=null] {expiryCallback} Callback when the countdown expires -
receives no parameters and this
is the containing division.
@example onExpiry: function() {
...
}
@property [onTick=null] {tickCallback} Callback when the countdown is updated -
receives number[7]
being the breakdown by period
(years, months, weeks, days, hours, minutes, seconds - based on
format
) and this
is the containing division.
@example onTick: function(periods) {
var secs = $.countdown.periodsToSeconds(periods);
if (secs < 300) { // Last five minutes
...
}
}
@property [tickInterval=1] {number} The interval (seconds) between onTick
callbacks. */
defaultOptions: {
until: null,
since: null,
timezone: null,
serverSync: null,
format: 'dHMS',
layout: '',
compact: false,
padZeroes: false,
significant: 0,
description: '',
expiryUrl: '',
expiryText: '',
alwaysExpire: false,
onExpiry: null,
onTick: null,
tickInterval: 1
},
/** Localisations for the plugin.
Entries are objects indexed by the language code ('' being the default US/English).
Each object has the following attributes.
@property [labels=['Years','Months','Weeks','Days','Hours','Minutes','Seconds']] {string[]}
The display texts for the counter periods.
@property [labels1=['Year','Month','Week','Day','Hour','Minute','Second']] {string[]}
The display texts for the counter periods if they have a value of 1.
Add other labelsn
attributes as necessary to
cater for other numeric idiosyncrasies of the localisation.
@property [compactLabels=['y','m','w','d']] {string[]} The compact texts for the counter periods.
@property [whichLabels=null] {whichLabelsCallback} A function to determine which
labelsn
to use.
@example whichLabels: function(num) {
return (num > 1 ? 0 : 1);
}
@property [digits=['0','1',...,'9']] {number[]} The digits to display (0-9).
@property [timeSeparator=':'] {string} Separator for time periods in the compact layout.
@property [isRTL=false] {boolean} True for right-to-left languages, false for left-to-right. */
regionalOptions: { // Available regional settings, indexed by language/country code
'': { // Default regional settings - English/US
labels: ['Years', 'Months', 'Weeks', 'Days', 'Hours', 'Minutes', 'Seconds'],
labels1: ['Year', 'Month', 'Week', 'Day', 'Hour', 'Minute', 'Second'],
compactLabels: ['y', 'm', 'w', 'd'],
whichLabels: null,
digits: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
timeSeparator: ':',
isRTL: false
}
},
/** Names of getter methods - those that can't be chained. */
_getters: ['getTimes'],
/* Class name for the right-to-left marker. */
_rtlClass: pluginName + '-rtl',
/* Class name for the countdown section marker. */
_sectionClass: pluginName + '-section',
/* Class name for the period amount marker. */
_amountClass: pluginName + '-amount',
/* Class name for the period name marker. */
_periodClass: pluginName + '-period',
/* Class name for the countdown row marker. */
_rowClass: pluginName + '-row',
/* Class name for the holding countdown marker. */
_holdingClass: pluginName + '-holding',
/* Class name for the showing countdown marker. */
_showClass: pluginName + '-show',
/* Class name for the description marker. */
_descrClass: pluginName + '-descr',
/* List of currently active countdown elements. */
_timerElems: [],
/** Additional setup for the countdown.
Apply default localisations.
Create the timer. */
_init: function() {
var self = this;
this._super();
this._serverSyncs = [];
var now = (typeof Date.now == 'function' ? Date.now :
function() { return new Date().getTime(); });
var perfAvail = (window.performance && typeof window.performance.now == 'function');
// Shared timer for all countdowns
function timerCallBack(timestamp) {
var drawStart = (timestamp < 1e12 ? // New HTML5 high resolution timer
(perfAvail ? (performance.now() + performance.timing.navigationStart) : now()) :
// Integer milliseconds since unix epoch
timestamp || now());
if (drawStart - animationStartTime >= 1000) {
self._updateElems();
animationStartTime = drawStart;
}
requestAnimationFrame(timerCallBack);
}
var requestAnimationFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame || window.msRequestAnimationFrame || null;
// This is when we expect a fall-back to setInterval as it's much more fluid
var animationStartTime = 0;
if (!requestAnimationFrame || $.noRequestAnimationFrame) {
$.noRequestAnimationFrame = null;
setInterval(function() { self._updateElems(); }, 980); // Fall back to good old setInterval
}
else {
animationStartTime = window.animationStartTime ||
window.webkitAnimationStartTime || window.mozAnimationStartTime ||
window.oAnimationStartTime || window.msAnimationStartTime || now();
requestAnimationFrame(timerCallBack);
}
},
/** Convert a date/time to UTC.
@param tz {number} The hour or minute offset from GMT, e.g. +9, -360.
@param year {Date|number} the date/time in that timezone or the year in that timezone.
@param [month] {number} The month (0 - 11) (omit if year
is a Date
).
@param [day] {number} The day (omit if year
is a Date
).
@param [hours] {number} The hour (omit if year
is a Date
).
@param [mins] {number} The minute (omit if year
is a Date
).
@param [secs] {number} The second (omit if year
is a Date
).
@param [ms] {number} The millisecond (omit if year
is a Date
).
@return {Date} The equivalent UTC date/time.
@example $.countdown.UTCDate(+10, 2013, 12-1, 25, 12, 0)
$.countdown.UTCDate(-7, new Date(2013, 12-1, 25, 12, 0)) */
UTCDate: function(tz, year, month, day, hours, mins, secs, ms) {
if (typeof year == 'object' && year.constructor == Date) {
ms = year.getMilliseconds();
secs = year.getSeconds();
mins = year.getMinutes();
hours = year.getHours();
day = year.getDate();
month = year.getMonth();
year = year.getFullYear();
}
var d = new Date();
d.setUTCFullYear(year);
d.setUTCDate(1);
d.setUTCMonth(month || 0);
d.setUTCDate(day || 1);
d.setUTCHours(hours || 0);
d.setUTCMinutes((mins || 0) - (Math.abs(tz) < 30 ? tz * 60 : tz));
d.setUTCSeconds(secs || 0);
d.setUTCMilliseconds(ms || 0);
return d;
},
/** Convert a set of periods into seconds.
Averaged for months and years.
@param periods {number[]} The periods per year/month/week/day/hour/minute/second.
@return {number} The corresponding number of seconds.
@example var secs = $.countdown.periodsToSeconds(periods) */
periodsToSeconds: function(periods) {
return periods[0] * 31557600 + periods[1] * 2629800 + periods[2] * 604800 +
periods[3] * 86400 + periods[4] * 3600 + periods[5] * 60 + periods[6];
},
/** Resynchronise the countdowns with the server.
@example $.countdown.resync() */
resync: function() {
var self = this;
$('.' + this._getMarker()).each(function() { // Each countdown
var inst = $.data(this, self.name);
if (inst.options.serverSync) { // If synced
var serverSync = null;
for (var i = 0; i < self._serverSyncs.length; i++) {
if (self._serverSyncs[i][0] == inst.options.serverSync) { // Find sync details
serverSync = self._serverSyncs[i];
break;
}
}
if (serverSync[2] == null) { // Recalculate if missing
var serverResult = ($.isFunction(inst.options.serverSync) ?
inst.options.serverSync.apply(this, []) : null);
serverSync[2] =
(serverResult ? new Date().getTime() - serverResult.getTime() : 0) - serverSync[1];
}
if (inst._since) { // Apply difference
inst._since.setMilliseconds(inst._since.getMilliseconds() + serverSync[2]);
}
inst._until.setMilliseconds(inst._until.getMilliseconds() + serverSync[2]);
}
});
for (var i = 0; i < self._serverSyncs.length; i++) { // Update sync details
if (self._serverSyncs[i][2] != null) {
self._serverSyncs[i][1] += self._serverSyncs[i][2];
delete self._serverSyncs[i][2];
}
}
},
_instSettings: function(elem, options) {
return {_periods: [0, 0, 0, 0, 0, 0, 0]};
},
/** Add an element to the list of active ones.
@private
@param elem {Element} The countdown element. */
_addElem: function(elem) {
if (!this._hasElem(elem)) {
this._timerElems.push(elem);
}
},
/** See if an element is in the list of active ones.
@private
@param elem {Element} The countdown element.
@return {boolean} True if present, false if not. */
_hasElem: function(elem) {
return ($.inArray(elem, this._timerElems) > -1);
},
/** Remove an element from the list of active ones.
@private
@param elem {Element} The countdown element. */
_removeElem: function(elem) {
this._timerElems = $.map(this._timerElems,
function(value) { return (value == elem ? null : value); }); // delete entry
},
/** Update each active timer element.
@private */
_updateElems: function() {
for (var i = this._timerElems.length - 1; i >= 0; i--) {
this._updateCountdown(this._timerElems[i]);
}
},
_optionsChanged: function(elem, inst, options) {
if (options.layout) {
options.layout = options.layout.replace(/</g, '<').replace(/>/g, '>');
}
this._resetExtraLabels(inst.options, options);
var timezoneChanged = (inst.options.timezone != options.timezone);
$.extend(inst.options, options);
this._adjustSettings(elem, inst,
options.until != null || options.since != null || timezoneChanged);
var now = new Date();
if ((inst._since && inst._since < now) || (inst._until && inst._until > now)) {
this._addElem(elem[0]);
}
this._updateCountdown(elem, inst);
},
/** Redisplay the countdown with an updated display.
@private
@param elem {Element|jQuery} The containing division.
@param inst {object} The current settings for this instance. */
_updateCountdown: function(elem, inst) {
elem = elem.jquery ? elem : $(elem);
inst = inst || this._getInst(elem);
if (!inst) {
return;
}
elem.html(this._generateHTML(inst)).toggleClass(this._rtlClass, inst.options.isRTL);
if ($.isFunction(inst.options.onTick)) {
var periods = inst._hold != 'lap' ? inst._periods :
this._calculatePeriods(inst, inst._show, inst.options.significant, new Date());
if (inst.options.tickInterval == 1 ||
this.periodsToSeconds(periods) % inst.options.tickInterval == 0) {
inst.options.onTick.apply(elem[0], [periods]);
}
}
var expired = inst._hold != 'pause' &&
(inst._since ? inst._now.getTime() < inst._since.getTime() :
inst._now.getTime() >= inst._until.getTime());
if (expired && !inst._expiring) {
inst._expiring = true;
if (this._hasElem(elem[0]) || inst.options.alwaysExpire) {
this._removeElem(elem[0]);
if ($.isFunction(inst.options.onExpiry)) {
inst.options.onExpiry.apply(elem[0], []);
}
if (inst.options.expiryText) {
var layout = inst.options.layout;
inst.options.layout = inst.options.expiryText;
this._updateCountdown(elem[0], inst);
inst.options.layout = layout;
}
if (inst.options.expiryUrl) {
window.location = inst.options.expiryUrl;
}
}
inst._expiring = false;
}
else if (inst._hold == 'pause') {
this._removeElem(elem[0]);
}
},
/** Reset any extra labelsn and compactLabelsn entries if changing labels.
@private
@param base {object} The options to be updated.
@param options {object} The new option values. */
_resetExtraLabels: function(base, options) {
for (var n in options) {
if (n.match(/[Ll]abels[02-9]|compactLabels1/)) {
base[n] = options[n];
}
}
for (var n in base) { // Remove custom numbered labels
if (n.match(/[Ll]abels[02-9]|compactLabels1/) && typeof options[n] === 'undefined') {
base[n] = null;
}
}
},
/** Calculate internal settings for an instance.
@private
@param elem {jQuery} The containing division.
@param inst {object} The current settings for this instance.
@param recalc {boolean} True if until or since are set. */
_adjustSettings: function(elem, inst, recalc) {
var serverEntry = null;
for (var i = 0; i < this._serverSyncs.length; i++) {
if (this._serverSyncs[i][0] == inst.options.serverSync) {
serverEntry = this._serverSyncs[i][1];
break;
}
}
if (serverEntry != null) {
var serverOffset = (inst.options.serverSync ? serverEntry : 0);
var now = new Date();
}
else {
var serverResult = ($.isFunction(inst.options.serverSync) ?
inst.options.serverSync.apply(elem[0], []) : null);
var now = new Date();
var serverOffset = (serverResult ? now.getTime() - serverResult.getTime() : 0);
this._serverSyncs.push([inst.options.serverSync, serverOffset]);
}
var timezone = inst.options.timezone;
timezone = (timezone == null ? -now.getTimezoneOffset() : timezone);
if (recalc || (!recalc && inst._until == null && inst._since == null)) {
inst._since = inst.options.since;
if (inst._since != null) {
inst._since = this.UTCDate(timezone, this._determineTime(inst._since, null));
if (inst._since && serverOffset) {
inst._since.setMilliseconds(inst._since.getMilliseconds() + serverOffset);
}
}
inst._until = this.UTCDate(timezone, this._determineTime(inst.options.until, now));
if (serverOffset) {
inst._until.setMilliseconds(inst._until.getMilliseconds() + serverOffset);
}
}
inst._show = this._determineShow(inst);
},
/** Remove the countdown widget from a div.
@param elem {jQuery} The containing division.
@param inst {object} The current instance object. */
_preDestroy: function(elem, inst) {
this._removeElem(elem[0]);
elem.empty();
},
/** Pause a countdown widget at the current time.
Stop it running but remember and display the current time.
@param elem {Element} The containing division.
@example $(selector).countdown('pause') */
pause: function(elem) {
this._hold(elem, 'pause');
},
/** Pause a countdown widget at the current time.
Stop the display but keep the countdown running.
@param elem {Element} The containing division.
@example $(selector).countdown('lap') */
lap: function(elem) {
this._hold(elem, 'lap');
},
/** Resume a paused countdown widget.
@param elem {Element} The containing division.
@example $(selector).countdown('resume') */
resume: function(elem) {
this._hold(elem, null);
},
/** Toggle a paused countdown widget.
@param elem {Element} The containing division.
@example $(selector).countdown('toggle') */
toggle: function(elem) {
var inst = $.data(elem, this.name) || {};
this[!inst._hold ? 'pause' : 'resume'](elem);
},
/** Toggle a lapped countdown widget.
@param elem {Element} The containing division.
@example $(selector).countdown('toggleLap') */
toggleLap: function(elem) {
var inst = $.data(elem, this.name) || {};
this[!inst._hold ? 'lap' : 'resume'](elem);
},
/** Pause or resume a countdown widget.
@private
@param elem {Element} The containing division.
@param hold {string} The new hold setting. */
_hold: function(elem, hold) {
var inst = $.data(elem, this.name);
if (inst) {
if (inst._hold == 'pause' && !hold) {
inst._periods = inst._savePeriods;
var sign = (inst._since ? '-' : '+');
inst[inst._since ? '_since' : '_until'] =
this._determineTime(sign + inst._periods[0] + 'y' +
sign + inst._periods[1] + 'o' + sign + inst._periods[2] + 'w' +
sign + inst._periods[3] + 'd' + sign + inst._periods[4] + 'h' +
sign + inst._periods[5] + 'm' + sign + inst._periods[6] + 's');
this._addElem(elem);
}
inst._hold = hold;
inst._savePeriods = (hold == 'pause' ? inst._periods : null);
$.data(elem, this.name, inst);
this._updateCountdown(elem, inst);
}
},
/** Return the current time periods.
@param elem {Element} The containing division.
@return {number[]} The current periods for the countdown.
@example var periods = $(selector).countdown('getTimes') */
getTimes: function(elem) {
var inst = $.data(elem, this.name);
return (!inst ? null : (inst._hold == 'pause' ? inst._savePeriods : (!inst._hold ? inst._periods :
this._calculatePeriods(inst, inst._show, inst.options.significant, new Date()))));
},
/** A time may be specified as an exact value or a relative one.
@private
@param setting {string|number|Date} The date/time value as a relative or absolute value.
@param defaultTime {Date} The date/time to use if no other is supplied.
@return {Date} The corresponding date/time. */
_determineTime: function(setting, defaultTime) {
var self = this;
var offsetNumeric = function(offset) { // e.g. +300, -2
var time = new Date();
time.setTime(time.getTime() + offset * 1000);
return time;
};
var offsetString = function(offset) { // e.g. '+2d', '-4w', '+3h +30m'
offset = offset.toLowerCase();
var time = new Date();
var year = time.getFullYear();
var month = time.getMonth();
var day = time.getDate();
var hour = time.getHours();
var minute = time.getMinutes();
var second = time.getSeconds();
var pattern = /([+-]?[0-9]+)\s*(s|m|h|d|w|o|y)?/g;
var matches = pattern.exec(offset);
while (matches) {
switch (matches[2] || 's') {
case 's': second += parseInt(matches[1], 10); break;
case 'm': minute += parseInt(matches[1], 10); break;
case 'h': hour += parseInt(matches[1], 10); break;
case 'd': day += parseInt(matches[1], 10); break;
case 'w': day += parseInt(matches[1], 10) * 7; break;
case 'o':
month += parseInt(matches[1], 10);
day = Math.min(day, self._getDaysInMonth(year, month));
break;
case 'y':
year += parseInt(matches[1], 10);
day = Math.min(day, self._getDaysInMonth(year, month));
break;
}
matches = pattern.exec(offset);
}
return new Date(year, month, day, hour, minute, second, 0);
};
var time = (setting == null ? defaultTime :
(typeof setting == 'string' ? offsetString(setting) :
(typeof setting == 'number' ? offsetNumeric(setting) : setting)));
if (time) time.setMilliseconds(0);
return time;
},
/** Determine the number of days in a month.
@private
@param year {number} The year.
@param month {number} The month.
@return {number} The days in that month. */
_getDaysInMonth: function(year, month) {
return 32 - new Date(year, month, 32).getDate();
},
/** Default implementation to determine which set of labels should be used for an amount.
Use the labels
attribute with the same numeric suffix (if it exists).
@private
@param num {number} The amount to be displayed.
@return {number} The set of labels to be used for this amount. */
_normalLabels: function(num) {
return num;
},
/** Generate the HTML to display the countdown widget.
@private
@param inst {object} The current settings for this instance.
@return {string} The new HTML for the countdown display. */
_generateHTML: function(inst) {
var self = this;
// Determine what to show
inst._periods = (inst._hold ? inst._periods :
this._calculatePeriods(inst, inst._show, inst.options.significant, new Date()));
// Show all 'asNeeded' after first non-zero value
var shownNonZero = false;
var showCount = 0;
var sigCount = inst.options.significant;
var show = $.extend({}, inst._show);
for (var period = Y; period <= S; period++) {
shownNonZero |= (inst._show[period] == '?' && inst._periods[period] > 0);
show[period] = (inst._show[period] == '?' && !shownNonZero ? null : inst._show[period]);
showCount += (show[period] ? 1 : 0);
sigCount -= (inst._periods[period] > 0 ? 1 : 0);
}
var showSignificant = [false, false, false, false, false, false, false];
for (var period = S; period >= Y; period--) { // Determine significant periods
if (inst._show[period]) {
if (inst._periods[period]) {
showSignificant[period] = true;
}
else {
showSignificant[period] = sigCount > 0;
sigCount--;
}
}
}
var labels = (inst.options.compact ? inst.options.compactLabels : inst.options.labels);
var whichLabels = inst.options.whichLabels || this._normalLabels;
var showCompact = function(period) {
var labelsNum = inst.options['compactLabels' + whichLabels(inst._periods[period])];
return (show[period] ? self._translateDigits(inst, inst._periods[period]) +
(labelsNum ? labelsNum[period] : labels[period]) + ' ' : '');
};
var minDigits = (inst.options.padZeroes ? 2 : 1);
var showFull = function(period) {
var labelsNum = inst.options['labels' + whichLabels(inst._periods[period])];
return ((!inst.options.significant && show[period]) ||
(inst.options.significant && showSignificant[period]) ?
'' +
'' +
self._minDigits(inst, inst._periods[period], minDigits) + '' +
'' +
(labelsNum ? labelsNum[period] : labels[period]) + '' : '');
};
return (inst.options.layout ? this._buildLayout(inst, show, inst.options.layout,
inst.options.compact, inst.options.significant, showSignificant) :
((inst.options.compact ? // Compact version
'' +
showCompact(Y) + showCompact(O) + showCompact(W) + showCompact(D) +
(show[H] ? this._minDigits(inst, inst._periods[H], 2) : '') +
(show[M] ? (show[H] ? inst.options.timeSeparator : '') +
this._minDigits(inst, inst._periods[M], 2) : '') +
(show[S] ? (show[H] || show[M] ? inst.options.timeSeparator : '') +
this._minDigits(inst, inst._periods[S], 2) : '') :
// Full version
'' +
inst.options.description + '' : '')));
},
/** Construct a custom layout.
@private
@param inst {object} The current settings for this instance.
@param show {boolean[]} Flags indicating which periods are requested.
@param layout {string} The customised layout.
@param compact {boolean} True if using compact labels.
@param significant {number} The number of periods with values to show, zero for all.
@param showSignificant {boolean[]} Other periods to show for significance.
@return {string} The custom HTML. */
_buildLayout: function(inst, show, layout, compact, significant, showSignificant) {
var labels = inst.options[compact ? 'compactLabels' : 'labels'];
var whichLabels = inst.options.whichLabels || this._normalLabels;
var labelFor = function(index) {
return (inst.options[(compact ? 'compactLabels' : 'labels') +
whichLabels(inst._periods[index])] || labels)[index];
};
var digit = function(value, position) {
return inst.options.digits[Math.floor(value / position) % 10];
};
var subs = {desc: inst.options.description, sep: inst.options.timeSeparator,
yl: labelFor(Y), yn: this._minDigits(inst, inst._periods[Y], 1),
ynn: this._minDigits(inst, inst._periods[Y], 2),
ynnn: this._minDigits(inst, inst._periods[Y], 3), y1: digit(inst._periods[Y], 1),
y10: digit(inst._periods[Y], 10), y100: digit(inst._periods[Y], 100),
y1000: digit(inst._periods[Y], 1000),
ol: labelFor(O), on: this._minDigits(inst, inst._periods[O], 1),
onn: this._minDigits(inst, inst._periods[O], 2),
onnn: this._minDigits(inst, inst._periods[O], 3), o1: digit(inst._periods[O], 1),
o10: digit(inst._periods[O], 10), o100: digit(inst._periods[O], 100),
o1000: digit(inst._periods[O], 1000),
wl: labelFor(W), wn: this._minDigits(inst, inst._periods[W], 1),
wnn: this._minDigits(inst, inst._periods[W], 2),
wnnn: this._minDigits(inst, inst._periods[W], 3), w1: digit(inst._periods[W], 1),
w10: digit(inst._periods[W], 10), w100: digit(inst._periods[W], 100),
w1000: digit(inst._periods[W], 1000),
dl: labelFor(D), dn: this._minDigits(inst, inst._periods[D], 1),
dnn: this._minDigits(inst, inst._periods[D], 2),
dnnn: this._minDigits(inst, inst._periods[D], 3), d1: digit(inst._periods[D], 1),
d10: digit(inst._periods[D], 10), d100: digit(inst._periods[D], 100),
d1000: digit(inst._periods[D], 1000),
hl: labelFor(H), hn: this._minDigits(inst, inst._periods[H], 1),
hnn: this._minDigits(inst, inst._periods[H], 2),
hnnn: this._minDigits(inst, inst._periods[H], 3), h1: digit(inst._periods[H], 1),
h10: digit(inst._periods[H], 10), h100: digit(inst._periods[H], 100),
h1000: digit(inst._periods[H], 1000),
ml: labelFor(M), mn: this._minDigits(inst, inst._periods[M], 1),
mnn: this._minDigits(inst, inst._periods[M], 2),
mnnn: this._minDigits(inst, inst._periods[M], 3), m1: digit(inst._periods[M], 1),
m10: digit(inst._periods[M], 10), m100: digit(inst._periods[M], 100),
m1000: digit(inst._periods[M], 1000),
sl: labelFor(S), sn: this._minDigits(inst, inst._periods[S], 1),
snn: this._minDigits(inst, inst._periods[S], 2),
snnn: this._minDigits(inst, inst._periods[S], 3), s1: digit(inst._periods[S], 1),
s10: digit(inst._periods[S], 10), s100: digit(inst._periods[S], 100),
s1000: digit(inst._periods[S], 1000)};
var html = layout;
// Replace period containers: {p<}...{p>}
for (var i = Y; i <= S; i++) {
var period = 'yowdhms'.charAt(i);
var re = new RegExp('\\{' + period + '<\\}([\\s\\S]*)\\{' + period + '>\\}', 'g');
html = html.replace(re, ((!significant && show[i]) ||
(significant && showSignificant[i]) ? '$1' : ''));
}
// Replace period values: {pn}
$.each(subs, function(n, v) {
var re = new RegExp('\\{' + n + '\\}', 'g');
html = html.replace(re, v);
});
return html;
},
/** Ensure a numeric value has at least n digits for display.
@private
@param inst {object} The current settings for this instance.
@param value {number} The value to display.
@param len {number} The minimum length.
@return {string} The display text. */
_minDigits: function(inst, value, len) {
value = '' + value;
if (value.length >= len) {
return this._translateDigits(inst, value);
}
value = '0000000000' + value;
return this._translateDigits(inst, value.substr(value.length - len));
},
/** Translate digits into other representations.
@private
@param inst {object} The current settings for this instance.
@param value {string} The text to translate.
@return {string} The translated text. */
_translateDigits: function(inst, value) {
return ('' + value).replace(/[0-9]/g, function(digit) {
return inst.options.digits[digit];
});
},
/** Translate the format into flags for each period.
@private
@param inst {object} The current settings for this instance.
@return {string[]} Flags indicating which periods are requested (?) or
required (!) by year, month, week, day, hour, minute, second. */
_determineShow: function(inst) {
var format = inst.options.format;
var show = [];
show[Y] = (format.match('y') ? '?' : (format.match('Y') ? '!' : null));
show[O] = (format.match('o') ? '?' : (format.match('O') ? '!' : null));
show[W] = (format.match('w') ? '?' : (format.match('W') ? '!' : null));
show[D] = (format.match('d') ? '?' : (format.match('D') ? '!' : null));
show[H] = (format.match('h') ? '?' : (format.match('H') ? '!' : null));
show[M] = (format.match('m') ? '?' : (format.match('M') ? '!' : null));
show[S] = (format.match('s') ? '?' : (format.match('S') ? '!' : null));
return show;
},
/** Calculate the requested periods between now and the target time.
@private
@param inst {object} The current settings for this instance.
@param show {string[]} Flags indicating which periods are requested/required.
@param significant {number} The number of periods with values to show, zero for all.
@param now {Date} The current date and time.
@return {number[]} The current time periods (always positive)
by year, month, week, day, hour, minute, second. */
_calculatePeriods: function(inst, show, significant, now) {
// Find endpoints
inst._now = now;
inst._now.setMilliseconds(0);
var until = new Date(inst._now.getTime());
if (inst._since) {
if (now.getTime() < inst._since.getTime()) {
inst._now = now = until;
}
else {
now = inst._since;
}
}
else {
until.setTime(inst._until.getTime());
if (now.getTime() > inst._until.getTime()) {
inst._now = now = until;
}
}
// Calculate differences by period
var periods = [0, 0, 0, 0, 0, 0, 0];
if (show[Y] || show[O]) {
// Treat end of months as the same
var lastNow = this._getDaysInMonth(now.getFullYear(), now.getMonth());
var lastUntil = this._getDaysInMonth(until.getFullYear(), until.getMonth());
var sameDay = (until.getDate() == now.getDate() ||
(until.getDate() >= Math.min(lastNow, lastUntil) &&
now.getDate() >= Math.min(lastNow, lastUntil)));
var getSecs = function(date) {
return (date.getHours() * 60 + date.getMinutes()) * 60 + date.getSeconds();
};
var months = Math.max(0,
(until.getFullYear() - now.getFullYear()) * 12 + until.getMonth() - now.getMonth() +
((until.getDate() < now.getDate() && !sameDay) ||
(sameDay && getSecs(until) < getSecs(now)) ? -1 : 0));
periods[Y] = (show[Y] ? Math.floor(months / 12) : 0);
periods[O] = (show[O] ? months - periods[Y] * 12 : 0);
// Adjust for months difference and end of month if necessary
now = new Date(now.getTime());
var wasLastDay = (now.getDate() == lastNow);
var lastDay = this._getDaysInMonth(now.getFullYear() + periods[Y],
now.getMonth() + periods[O]);
if (now.getDate() > lastDay) {
now.setDate(lastDay);
}
now.setFullYear(now.getFullYear() + periods[Y]);
now.setMonth(now.getMonth() + periods[O]);
if (wasLastDay) {
now.setDate(lastDay);
}
}
var diff = Math.floor((until.getTime() - now.getTime()) / 1000);
var extractPeriod = function(period, numSecs) {
periods[period] = (show[period] ? Math.floor(diff / numSecs) : 0);
diff -= periods[period] * numSecs;
};
extractPeriod(W, 604800);
extractPeriod(D, 86400);
extractPeriod(H, 3600);
extractPeriod(M, 60);
extractPeriod(S, 1);
if (diff > 0 && !inst._since) { // Round up if left overs
var multiplier = [1, 12, 4.3482, 7, 24, 60, 60];
var lastShown = S;
var max = 1;
for (var period = S; period >= Y; period--) {
if (show[period]) {
if (periods[lastShown] >= max) {
periods[lastShown] = 0;
diff = 1;
}
if (diff > 0) {
periods[period]++;
diff = 0;
lastShown = period;
max = 1;
}
}
max *= multiplier[period];
}
}
if (significant) { // Zero out insignificant periods
for (var period = Y; period <= S; period++) {
if (significant && periods[period]) {
significant--;
}
else if (!significant) {
periods[period] = 0;
}
}
}
return periods;
}
});
})(jQuery);
/*! pro-elements - v3.23.0 - 05-08-2024 */
.elementor-payment-button{border:none}# Payment-Button.php
## Technical Description:
This is an abstract class that every payment button widget will inherit from.
Because every payment button is, after all, a button, this class inherits from `Widget_Button`
in order to keep it as close as possible to the default button widget ( and of course to avoid unnecessary code duplications ).
This class is responsible for creating the universal sections && controls of the payment buttons.
In addition, it has some abstract functions to make sure that every payment button will work as it should.
## Attention Needed / Known Issues:
- Use the `register_account_section()` function in order to add the API controls for your payment provider.
See `widgets/paypal-button.php` for reference.
- Use the `register_sandbox_controls()` function if you need more sandbox controls than the default `sandbox_mode` switch.
By default, they will be registered just after the switch.
- Use the `after_product_type()` function when you need to add something after the product type select-box. This is useful when you want to add a
note to the user.
See `widgets/paypal-button.php` for reference.
- Use the `after_custom_messages_toggle()` function when you need to add something after the `custom_messages` control.
- The currencies list **defaults to PayPal's supported currencies**, so when you extend it, make sure that this list
is also supported in the payment method you are using, or override it with the appropriate one.
- The `get_custom_message( $id )` returns a custom message that is set in the `Custom Messages` control under the `Additional Settings` section, and will default to
the default errors messages that returned from `get_default_error_messages()`.
You can override this function in order to extend the default custom messages. Don't forget to extend the `register_settings_section()` and `register_messages_style_section()` functions as well.
- You should use `is_sandbox()` to determine if it's on sandbox mode.
@font-face {
font-family: 'Master-Addons';
src: url('../fonts/Master-Addons/Master-Addons.eot?e493qi');
src: url('../fonts/Master-Addons/Master-Addons.eot?e493qi#iefix') format('embedded-opentype'),
url('../fonts/Master-Addons/Master-Addons.ttf?e493qi') format('truetype'),
url('../fonts/Master-Addons/Master-Addons.woff?e493qi') format('woff'),
url('../fonts/Master-Addons/Master-Addons.svg?e493qi#Master-Addons') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
}
[class^="jltma-icon-"],
[class*=" jltma-icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */
speak: never;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.jltma-icon-ma:after {
content : "\e901";
color : #fff;
background : rgb(74, 77, 236);
border-radius: 15px;
margin-left : -1em;
position : absolute;
top : 15px;
right : 15px;
font-size : 18px;
opacity : .6;
font-family : 'Master-Addons' !important;
}
.jltma-icon {
color: #e0e1e3;
}
#elementor-panel #elementor-panel-header-title span.jltma-badge:after,
#elementor-panel .elementor-control-title span.jltma-badge:after,
#elementor-panel .elementor-section-title span.jltma-badge:after {
content: "MA";
background-color: #fff;
color: #d30c5c;
font-size: 10px;
font-weight: 700;
border-radius: 30px;
padding: 2px 3px;
margin-right: 4px;
vertical-align: middle;
}
#elementor-panel .elementor-control-title span.jltma-badge:after,
#elementor-panel .elementor-section-title span.jltma-badge:after {
background-color: #e0e6ec;
color: #50565d;
}
.jltma-editor-doc-links {
font-size: 12px;
}
.jltma-editor-doc-links a {
color: #999 !important;
display: inline-block;
line-height: 1.2;
padding-left: 10px;
position: relative;
}
.jltma-editor-doc-links a:hover {
color: #cf0c5d !important;
}
.jltma-editor-doc-links a:before {
content: "»";
position: absolute;
left: 0;
top: 0;
}
/* Tabs Section Identifier */
/*div[class*="elementor-control-ma_el"]:before{
content: 'Master Addons';
letter-spacing: 0.1em;
color: #aaa;
}
div[class*="elementor-control-ma_"]:before {
position: absolute;
top: 13px;
right: 8px;
text-transform: uppercase;
font-size: 9px;
padding: 2px 2px 1px;
border: 1px solid #ddd;
font-weight: 400;
letter-spacing: 0.1em;
color: #aaa;
}
*/
/* Master Custom Breakpoint */
.master-cbp-device-landscape {
transform: rotate(90deg);
}
.elementor-panel .elementor-panel-footer-sub-menu-item {
padding: 3px 0;
}
#elementor-panel-footer-responsive .elementor-panel-footer-sub-menu {
overflow-y: auto;
height: 400px;
max-height: 30vh;
}
.elementor-panel-footer-sub-menu-item i.master-cbp-device {
background-position: center center;
background-repeat: no-repeat;
background-size: 20px 20px;
}
.elementor-responsive-switcher i.master-cbp-device {
width: 20px;
height: 20px;
}
#elementor-panel-footer-responsive .tooltip-target[class*="eicon-device-"] {
background-position: center center;
background-repeat: no-repeat;
background-size: 20px 20px;
}
/* overlapping the device popup */
.elementor-control-responsive-switchers .elementor-control-responsive-switchers__holder {
top: 50% !important;
bottom: auto !important;
transform: translateY(-50%) !important;
}
/* Text Choose Control */
.elementor-control-type-jltma-choose-text.elementor-label-inline>.elementor-control-content>.elementor-control-field>.elementor-control-input-wrapper {
width: auto;
min-width: 52%;
}
.elementor-control-type-jltma-choose-text .elementor-choices {
-webkit-box-pack: end;
-webkit-justify-content: flex-end;
-ms-flex-pack: end;
justify-content: flex-end;
}
.elementor-control-type-jltma-choose-text .elementor-choices .elementor-choices-label {
font-size: 10px;
text-transform: uppercase;
width: 50%;
min-width: -webkit-fit-content;
min-width: fit-content;
min-width: -moz-fit-content;
padding: 0 7px;
}
.elementor-control-type-jltma-choose-text.elementor-label-block .elementor-choices {
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
}
.elementor-control-type-jltma-choose-text.elementor-label-block .elementor-choices .elementor-choices-label {
white-space: nowrap;
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
overflow: hidden;
}
.elementor-control-type-jltma-choose-text.elementor-label-inline>.elementor-control-content>.elementor-control-field>.elementor-control-input-wrapper {
width: auto;
min-width: 52%;
}
/*! elementor - v3.21.0 - 15-04-2024 */
"use strict";(self.webpackChunkelementor=self.webpackChunkelementor||[]).push([[2343],{87206:(e,t,n)=>{var o=n(23615),r=n(38003).__,a=n(73203);Object.defineProperty(t,"__esModule",{value:!0}),t.default=ElementorLoading;var i=a(n(87363));function ElementorLoading(e){return i.default.createElement("div",{className:"elementor-loading"},i.default.createElement("div",{className:"elementor-loader-wrapper"},i.default.createElement("div",{className:"elementor-loader"},i.default.createElement("div",{className:"elementor-loader-boxes"},i.default.createElement("div",{className:"elementor-loader-box"}),i.default.createElement("div",{className:"elementor-loader-box"}),i.default.createElement("div",{className:"elementor-loader-box"}),i.default.createElement("div",{className:"elementor-loader-box"}))),i.default.createElement("div",{className:"elementor-loading-title"},e.loadingText)))}ElementorLoading.propTypes={loadingText:o.string},ElementorLoading.defaultProps={loadingText:r("Loading","elementor")}},15368:(e,t,n)=>{var o=n(23615),r=n(7501);Object.defineProperty(t,"__esModule",{value:!0}),t.default=PopoverDialog;var a=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!==r(e)&&"function"!=typeof e)return{default:e};var n=_getRequireWildcardCache(t);if(n&&n.has(e))return n.get(e);var o={},a=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if("default"!==i&&Object.prototype.hasOwnProperty.call(e,i)){var l=a?Object.getOwnPropertyDescriptor(e,i):null;l&&(l.get||l.set)?Object.defineProperty(o,i,l):o[i]=e[i]}o.default=e,n&&n.set(e,o);return o}(n(87363));function _getRequireWildcardCache(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(_getRequireWildcardCache=function _getRequireWildcardCache(e){return e?n:t})(e)}function PopoverDialog(e){var t=e.targetRef,n=e.offsetTop,o=e.offsetLeft,r=e.wrapperClass,i=e.trigger,l=e.hideAfter,c=(0,a.useCallback)((function(e){var r=null==t?void 0:t.current;if(r&&e){var a=function showPopover(){e.style.display="block",e.setAttribute("aria-expanded",!0);var t=r.getBoundingClientRect(),a=e.getBoundingClientRect(),i=a.width-t.width;e.style.top=t.bottom+n+"px",e.style.left=t.left-i/2-o+"px",e.style.setProperty("--popover-arrow-offset-end",(a.width-16)/2+"px")},c=function hidePopover(){e.style.display="none",e.setAttribute("aria-expanded",!1)};"hover"===i?function handlePopoverHover(){var t=!0,n=null;r.addEventListener("mouseover",(function(){t=!0,a()})),r.addEventListener("mouseleave",(function(){n=setTimeout((function(){t&&"block"===e.style.display&&c()}),l)})),e.addEventListener("mouseover",(function(){t=!1,n&&(clearTimeout(n),n=null)})),e.addEventListener("mouseleave",(function(){n=setTimeout((function(){t&&"block"===e.style.display&&c()}),l),t=!0}))}():"click"===i&&function handlePopoverClick(){var t=!1;r.addEventListener("click",(function(e){e.preventDefault(),e.stopPropagation(),t?(c(),t=!1):(a(),t=!0)})),e.addEventListener("click",(function(e){e.stopPropagation()})),document.body.addEventListener("click",(function(){t&&(c(),t=!1)}))}()}}),[t]),u="e-app__popover";return r&&(u+=" "+r),a.default.createElement("div",{className:u,ref:c},e.children)}PopoverDialog.propTypes={targetRef:o.oneOfType([o.func,o.shape({current:o.any})]).isRequired,trigger:o.string,direction:o.string,offsetTop:o.oneOfType([o.string,o.number]),offsetLeft:o.oneOfType([o.string,o.number]),wrapperClass:o.string,children:o.any,hideAfter:o.number},PopoverDialog.defaultProps={direction:"bottom",trigger:"hover",offsetTop:10,offsetLeft:0,hideAfter:300}},60458:(e,t,n)=>{var o=n(73203),r=n(7501);Object.defineProperty(t,"__esModule",{value:!0}),t.default=function App(){return(0,a.useEffect)((function(){var e="eps-theme-dark",t=document.body.classList.contains(e);if(t&&document.body.classList.remove(e),!elementorAppConfig.onboarding.onboardingAlreadyRan){var n=new FormData;n.append("_nonce",elementorCommon.config.ajax.nonce),n.append("action","elementor_update_onboarding_option"),fetch(elementorCommon.config.ajax.url,{method:"POST",body:n})}return elementorAppConfig.return_url=elementorAppConfig.admin_url,function(){t&&document.body.classList.add(e)}}),[]),a.default.createElement(c.ContextProvider,null,a.default.createElement(i.LocationProvider,{history:l.default.appHistory},a.default.createElement(i.Router,null,a.default.createElement(u.default,{default:!0}),a.default.createElement(s.default,{path:"hello"}),a.default.createElement(d.default,{path:"siteName"}),a.default.createElement(p.default,{path:"siteLogo"}),a.default.createElement(f.default,{path:"goodToGo"}),a.default.createElement(m.default,{path:"uploadAndInstallPro"}))))};var a=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!==r(e)&&"function"!=typeof e)return{default:e};var n=_getRequireWildcardCache(t);if(n&&n.has(e))return n.get(e);var o={},a=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if("default"!==i&&Object.prototype.hasOwnProperty.call(e,i)){var l=a?Object.getOwnPropertyDescriptor(e,i):null;l&&(l.get||l.set)?Object.defineProperty(o,i,l):o[i]=e[i]}o.default=e,n&&n.set(e,o);return o}(n(87363)),i=n(50927),l=o(n(3869)),c=n(33959),u=o(n(1103)),s=o(n(92728)),d=o(n(78270)),p=o(n(90013)),f=o(n(79914)),m=o(n(3902));function _getRequireWildcardCache(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(_getRequireWildcardCache=function _getRequireWildcardCache(e){return e?n:t})(e)}},36608:(e,t,n)=>{var o=n(23615),r=n(73203);Object.defineProperty(t,"__esModule",{value:!0}),t.default=Button;var a=r(n(87363));function Button(e){var t=e.buttonSettings,n=e.type,o="e-onboarding__button";return n&&(o+=" e-onboarding__button-".concat(n)),t.className?t.className+=" "+o:t.className=o,t.href?a.default.createElement("a",t,t.text):a.default.createElement("div",t,t.text)}Button.propTypes={buttonSettings:o.object.isRequired,type:o.string}},32389:(e,t,n)=>{var o=n(23615),r=n(73203);Object.defineProperty(t,"__esModule",{value:!0}),t.default=Card;var a=r(n(87363));function Card(e){var t=e.image,n=e.imageAlt,o=e.text,r=e.link,i=e.name,l=e.clickAction;return a.default.createElement("a",{className:"e-onboarding__card",href:r,onClick:function onClick(){elementorCommon.events.dispatchEvent({event:"starting canvas click",version:"",details:{placement:elementorAppConfig.onboarding.eventPlacement,selection:i}}),l&&l()}},a.default.createElement("img",{className:"e-onboarding__card-image",src:t,alt:n}),a.default.createElement("div",{className:"e-onboarding__card-text"},o))}Card.propTypes={image:o.string.isRequired,imageAlt:o.string.isRequired,text:o.string.isRequired,link:o.string.isRequired,name:o.string.isRequired,clickAction:o.func}},74233:(e,t,n)=>{var o=n(23615),r=n(73203);Object.defineProperty(t,"__esModule",{value:!0}),t.default=ChecklistItem;var a=r(n(87363));function ChecklistItem(e){return a.default.createElement("li",{className:"e-onboarding__checklist-item"},a.default.createElement("i",{className:"eicon-check-circle"}),e.children)}ChecklistItem.propTypes={children:o.string}},51224:(e,t,n)=>{var o=n(23615),r=n(73203);Object.defineProperty(t,"__esModule",{value:!0}),t.default=Checklist;var a=r(n(87363));function Checklist(e){return a.default.createElement("ul",{className:"e-onboarding__checklist"},e.children)}Checklist.propTypes={children:o.any.isRequired}},47707:(e,t,n)=>{var o=n(38003).__,r=n(23615),a=n(73203),i=n(7501);Object.defineProperty(t,"__esModule",{value:!0}),t.default=GoProPopover;var l=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!==i(e)&&"function"!=typeof e)return{default:e};var n=_getRequireWildcardCache(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var l=r?Object.getOwnPropertyDescriptor(e,a):null;l&&(l.get||l.set)?Object.defineProperty(o,a,l):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(87363)),c=n(33959),u=a(n(15368)),s=a(n(51224)),d=a(n(74233)),p=a(n(36608));function _getRequireWildcardCache(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(_getRequireWildcardCache=function _getRequireWildcardCache(e){return e?n:t})(e)}function GoProPopover(e){var t=(0,l.useContext)(c.OnboardingContext),n=t.state,r=t.updateState,a=(0,l.useCallback)((function(e){e&&e.addEventListener("click",(function(t){t.preventDefault(),elementorCommon.events.dispatchEvent({event:"already have pro",version:"",details:{placement:elementorAppConfig.onboarding.eventPlacement,step:n.currentStep}}),window.open(e.href+"&mode=popup","elementorUploadPro","toolbar=no, menubar=no, width=728, height=531, top=100, left=100"),elementorCommon.elements.$body.on("elementor/upload-and-install-pro/success",(function(){r({hasPro:!0,proNotice:{type:"success",icon:"eicon-check-circle-o",message:o("Elementor Pro has been successfully installed.","elementor")}})}))}))}),[]),i=e.buttonsConfig.find((function(e){return"go-pro"===e.id})),f={text:o("Upgrade Now","elementor"),className:"e-onboarding__go-pro-cta",target:"_blank",href:"https://elementor.com/pro/?utm_source=onboarding-wizard&utm_campaign=gopro&utm_medium=wp-dash&utm_content=top-bar-dropdown&utm_term="+elementorAppConfig.onboarding.onboardingVersion,tabIndex:0,onClick:function onClick(){elementorCommon.events.dispatchEvent({event:"get elementor pro",version:"",details:{placement:elementorAppConfig.onboarding.eventPlacement,step:n.currentStep}})}};return l.default.createElement(u.default,{targetRef:i.elRef,wrapperClass:"e-onboarding__go-pro"},l.default.createElement("div",{className:"e-onboarding__go-pro-content"},l.default.createElement("h2",{className:"e-onboarding__go-pro-title"},o("Ready to Get Elementor Pro?","elementor")),l.default.createElement(s.default,null,l.default.createElement(d.default,null,o("90+ Basic & Pro widgets","elementor")),l.default.createElement(d.default,null,o("300+ Basic & Pro templates","elementor")),l.default.createElement(d.default,null,o("Premium Support","elementor"))),l.default.createElement("div",{className:"e-onboarding__go-pro-paragraph"},o("And so much more!","elementor")),l.default.createElement("div",{className:"e-onboarding__go-pro-paragraph"},l.default.createElement(p.default,{buttonSettings:f})),l.default.createElement("div",{className:"e-onboarding__go-pro-paragraph"},l.default.createElement("a",{tabIndex:"0",className:"e-onboarding__go-pro-already-have",ref:a,href:elementorAppConfig.onboarding.urls.uploadPro,rel:"opener"},o("Already have Elementor Pro?","elementor")))))}GoProPopover.propTypes={buttonsConfig:r.array.isRequired}},3e4:(e,t,n)=>{var o=n(23615),r=n(73203);Object.defineProperty(t,"__esModule",{value:!0}),t.default=FooterButtons;var a=r(n(87363)),i=r(n(67096)),l=r(n(36608)),c=r(n(63878));function FooterButtons(e){var t=e.actionButton,n=e.skipButton,o=e.className,r="e-onboarding__footer";return o&&(r+=" "+o),a.default.createElement(i.default,{container:!0,alignItems:"center",justify:"space-between",className:r},t&&a.default.createElement(l.default,{buttonSettings:t,type:"action"}),n&&a.default.createElement(c.default,{button:n}))}FooterButtons.propTypes={actionButton:o.object,skipButton:o.object,className:o.string}},55020:(e,t,n)=>{var o=n(38003).__,r=n(23615),a=n(73203),i=n(7501);Object.defineProperty(t,"__esModule",{value:!0}),t.default=Header;var l=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!==i(e)&&"function"!=typeof e)return{default:e};var n=_getRequireWildcardCache(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var l=r?Object.getOwnPropertyDescriptor(e,a):null;l&&(l.get||l.set)?Object.defineProperty(o,a,l):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(87363)),c=n(33959),u=a(n(67096)),s=a(n(47707)),d=a(n(78419)),p=a(n(78845));function _getRequireWildcardCache(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(_getRequireWildcardCache=function _getRequireWildcardCache(e){return e?n:t})(e)}function Header(e){(0,p.default)({title:e.title});var t=(0,l.useContext)(c.OnboardingContext).state;return l.default.createElement(u.default,{container:!0,alignItems:"center",justify:"space-between",className:"eps-app__header e-onboarding__header"},l.default.createElement("div",{className:"eps-app__logo-title-wrapper e-onboarding__header-logo"},l.default.createElement("i",{className:"eps-app__logo eicon-elementor"}),l.default.createElement("img",{src:elementorCommon.config.urls.assets+"images/logo-platform.svg",alt:o("Elementor Logo","elementor")})),l.default.createElement(d.default,{buttons:e.buttons,onClose:function onClose(){elementorCommon.events.dispatchEvent({event:"close modal",version:"",details:{placement:elementorAppConfig.onboarding.eventPlacement,step:t.currentStep}}),window.top.location=elementorAppConfig.admin_url}}),!t.hasPro&&l.default.createElement(s.default,{buttonsConfig:e.buttons}))}Header.propTypes={title:r.string,buttons:r.arrayOf(r.object)},Header.defaultProps={buttons:[]}},8915:(e,t,n)=>{var o=n(38003).__,r=n(23615),a=n(73203),i=n(7501);Object.defineProperty(t,"__esModule",{value:!0}),t.default=Layout;var l=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!==i(e)&&"function"!=typeof e)return{default:e};var n=_getRequireWildcardCache(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var l=r?Object.getOwnPropertyDescriptor(e,a):null;l&&(l.get||l.set)?Object.defineProperty(o,a,l):o[a]=e[a]}o.default=e,n&&n.set(e,o);return o}(n(87363)),c=n(33959),u=a(n(55020)),s=a(n(4069)),d=a(n(88138)),p=a(n(94170));function _getRequireWildcardCache(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(_getRequireWildcardCache=function _getRequireWildcardCache(e){return e?n:t})(e)}function Layout(e){(0,l.useEffect)((function(){elementorCommon.events.dispatchEvent({event:"modal load",version:"",details:{placement:elementorAppConfig.onboarding.eventPlacement,step:e.pageId,user_state:elementorCommon.config.library_connect.is_connected?"logged":"anon"}}),r({currentStep:e.pageId,nextStep:e.nextStep||"",proNotice:null})}),[e.pageId]);var t=(0,l.useContext)(c.OnboardingContext),n=t.state,r=t.updateState,a=[],i=(0,l.useRef)(),f={id:"create-account",text:o("Create Account","elementor"),hideText:!1,elRef:(0,l.useRef)(),url:elementorAppConfig.onboarding.urls.signUp+elementorAppConfig.onboarding.utms.connectTopBar,target:"_blank",rel:"opener",onClick:function onClick(){elementorCommon.events.dispatchEvent({event:"create account",version:"",details:{placement:elementorAppConfig.onboarding.eventPlacement,step:n.currentStep,source:"header"}})}};return n.isLibraryConnected?a.push({id:"my-elementor",text:o("My Elementor","elementor"),hideText:!1,icon:"eicon-user-circle-o",url:"https://my.elementor.com/websites/?utm_source=onboarding-wizard&utm_medium=wp-dash&utm_campaign=my-account&utm_content=top-bar&utm_term="+elementorAppConfig.onboarding.onboardingVersion,target:"_blank",onClick:function onClick(){elementorCommon.events.dispatchEvent({event:"my elementor click",version:"",details:{placement:elementorAppConfig.onboarding.eventPlacement,step:n.currentStep,source:"header"}})}}):a.push(f),n.hasPro||a.push({id:"go-pro",text:o("Upgrade","elementor"),hideText:!1,className:"eps-button__go-pro-btn",url:"https://elementor.com/pro/?utm_source=onboarding-wizard&utm_campaign=gopro&utm_medium=wp-dash&utm_content=top-bar&utm_term="+elementorAppConfig.onboarding.onboardingVersion,target:"_blank",elRef:i,onClick:function onClick(){elementorCommon.events.dispatchEvent({event:"go pro",version:"",details:{placement:elementorAppConfig.onboarding.eventPlacement,step:n.currentStep}})}}),l.default.createElement("div",{className:"eps-app__lightbox"},l.default.createElement("div",{className:"eps-app e-onboarding"},!n.isLibraryConnected&&l.default.createElement(p.default,{buttonRef:f.elRef}),l.default.createElement(u.default,{title:o("Getting Started","elementor"),buttons:a}),l.default.createElement("div",{className:"eps-app__main e-onboarding__page-"+e.pageId},l.default.createElement(d.default,{className:"e-onboarding__content"},l.default.createElement(s.default,null),e.children))))}Layout.propTypes={pageId:r.string.isRequired,nextStep:r.string,className:r.string,children:r.any.isRequired}},61961:(e,t,n)=>{var o=n(23615),r=n(73203),a=n(7501);Object.defineProperty(t,"__esModule",{value:!0}),t.default=PageContentLayout;var i=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!==a(e)&&"function"!=typeof e)return{default:e};var n=_getRequireWildcardCache(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if("default"!==i&&Object.prototype.hasOwnProperty.call(e,i)){var l=r?Object.getOwnPropertyDescriptor(e,i):null;l&&(l.get||l.set)?Object.defineProperty(o,i,l):o[i]=e[i]}o.default=e,n&&n.set(e,o);return o}(n(87363)),l=n(33959),c=r(n(67096)),u=r(n(54041)),s=r(n(3e4));function _getRequireWildcardCache(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(_getRequireWildcardCache=function _getRequireWildcardCache(e){return e?n:t})(e)}function PageContentLayout(e){var t=(0,i.useContext)(l.OnboardingContext).state;return i.default.createElement(i.default.Fragment,null,i.default.createElement(c.default,{container:!0,alignItems:"center",justify:"space-between",className:"e-onboarding__page-content"},i.default.createElement("div",{className:"e-onboarding__page-content-start"},i.default.createElement("h1",{className:"e-onboarding__page-content-section-title"},e.title),i.default.createElement("div",{className:"e-onboarding__page-content-section-text"},e.children)),i.default.createElement("div",{className:"e-onboarding__page-content-end"},i.default.createElement("img",{src:e.image,alt:"Information"}))),i.default.createElement("div",{className:"e-onboarding__notice-container"},e.noticeState||t.proNotice?function printNotices(){return i.default.createElement(i.default.Fragment,null,e.noticeState&&i.default.createElement(u.default,{noticeState:e.noticeState}),t.proNotice&&i.default.createElement(u.default,{noticeState:t.proNotice}))}():i.default.createElement("div",{className:"e-onboarding__notice-empty-spacer"})),i.default.createElement(s.default,{actionButton:e.actionButton,skipButton:e.skipButton}))}PageContentLayout.propTypes={title:o.string,children:o.any,image:o.string,actionButton:o.object,skipButton:o.object,noticeState:o.any}},54041:(e,t,n)=>{var o=n(23615),r=n(73203);Object.defineProperty(t,"__esModule",{value:!0}),t.default=Notice;var a=r(n(87363));function Notice(e){return a.default.createElement("div",{className:"e-onboarding__notice e-onboarding__notice--".concat(e.noticeState.type)},a.default.createElement("i",{className:e.noticeState.icon}),a.default.createElement("span",{className:"e-onboarding__notice-text"},e.noticeState.message))}Notice.propTypes={noticeState:o.object}},18662:(e,t,n)=>{var o=n(23615),r=n(7501);Object.defineProperty(t,"__esModule",{value:!0}),t.default=ProgressBarItem;var a=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!==r(e)&&"function"!=typeof e)return{default:e};var n=_getRequireWildcardCache(t);if(n&&n.has(e))return n.get(e);var o={},a=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if("default"!==i&&Object.prototype.hasOwnProperty.call(e,i)){var l=a?Object.getOwnPropertyDescriptor(e,i):null;l&&(l.get||l.set)?Object.defineProperty(o,i,l):o[i]=e[i]}o.default=e,n&&n.set(e,o);return o}(n(87363)),i=n(33959);function _getRequireWildcardCache(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(_getRequireWildcardCache=function _getRequireWildcardCache(e){return e?n:t})(e)}function ProgressBarItem(e){var t=(0,a.useContext)(i.OnboardingContext).state,n="completed"===t.steps[e.id],o="skipped"===t.steps[e.id],r="e-onboarding__progress-bar-item";return e.id===t.currentStep?r+=" e-onboarding__progress-bar-item--active":n?r+=" e-onboarding__progress-bar-item--completed":o&&(r+=" e-onboarding__progress-bar-item--skipped"),a.default.createElement("div",{onClick:e.onClick,className:r},a.default.createElement("div",{className:"e-onboarding__progress-bar-item-icon"},n?a.default.createElement("i",{className:"eicon-check"}):e.index+1),e.title)}ProgressBarItem.propTypes={index:o.number.isRequired,id:o.string.isRequired,title:o.string.isRequired,route:o.string,onClick:o.func}},4069:(e,t,n)=>{var o=n(38003).__,r=n(73203),a=n(7501);Object.defineProperty(t,"__esModule",{value:!0}),t.default=function ProgressBar(){var e=(0,i.useContext)(c.OnboardingContext).state,t=(0,u.useNavigate)(),n=[{id:"account",title:o("Elementor Account","elementor"),route:"account"}];elementorAppConfig.onboarding.helloActivated||n.push({id:"hello",title:o("Hello Theme","elementor"),route:"hello"});n.push({id:"siteName",title:o("Site Name","elementor"),route:"site-name"},{id:"siteLogo",title:o("Site Logo","elementor"),route:"site-logo"},{id:"goodToGo",title:o("Good to Go","elementor"),route:"good-to-go"});var r=n.map((function(n,o){return n.index=o,e.steps[n.id]&&(n.onClick=function(){elementorCommon.events.dispatchEvent({event:"step click",version:"",details:{placement:elementorAppConfig.onboarding.eventPlacement,step:e.currentStep,next_step:n.id}}),t("/onboarding/"+n.id)}),i.default.createElement(s.default,(0,l.default)({key:n.id},n))}));return i.default.createElement("div",{className:"e-onboarding__progress-bar"},r)};var i=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!==a(e)&&"function"!=typeof e)return{default:e};var n=_getRequireWildcardCache(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if("default"!==i&&Object.prototype.hasOwnProperty.call(e,i)){var l=r?Object.getOwnPropertyDescriptor(e,i):null;l&&(l.get||l.set)?Object.defineProperty(o,i,l):o[i]=e[i]}o.default=e,n&&n.set(e,o);return o}(n(87363)),l=r(n(73119)),c=n(33959),u=n(50927),s=r(n(18662));function _getRequireWildcardCache(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(_getRequireWildcardCache=function _getRequireWildcardCache(e){return e?n:t})(e)}},63878:(e,t,n)=>{var o=n(23615),r=n(73203),a=n(7501);Object.defineProperty(t,"__esModule",{value:!0}),t.default=SkipButton;var i=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!==a(e)&&"function"!=typeof e)return{default:e};var n=_getRequireWildcardCache(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if("default"!==i&&Object.prototype.hasOwnProperty.call(e,i)){var l=r?Object.getOwnPropertyDescriptor(e,i):null;l&&(l.get||l.set)?Object.defineProperty(o,i,l):o[i]=e[i]}o.default=e,n&&n.set(e,o);return o}(n(87363)),l=n(33959),c=n(50927),u=r(n(36608));function _getRequireWildcardCache(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(_getRequireWildcardCache=function _getRequireWildcardCache(e){return e?n:t})(e)}function SkipButton(e){var t=e.button,n=e.className,o=(0,i.useContext)(l.OnboardingContext),r=o.state,a=o.updateState,s=(0,c.useNavigate)(),d=t.action||function skipStep(){var e=JSON.parse(JSON.stringify(r));e.steps[r.currentStep]="skipped",a(e),r.nextStep&&s("onboarding/"+r.nextStep)};return delete t.action,t.onClick=function(){elementorCommon.events.dispatchEvent({event:"skip",version:"",details:{placement:elementorAppConfig.onboarding.eventPlacement,step:r.currentStep}}),t.href||d()},i.default.createElement(u.default,{buttonSettings:t,className:n,type:"skip"})}SkipButton.propTypes={button:o.object.isRequired,className:o.string}},33959:(e,t,n)=>{var o=n(23615),r=n(73203),a=n(7501);Object.defineProperty(t,"__esModule",{value:!0}),t.ContextProvider=ContextProvider,t.OnboardingContext=void 0;var i=function _interopRequireWildcard(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!==a(e)&&"function"!=typeof e)return{default:e};var n=_getRequireWildcardCache(t);if(n&&n.has(e))return n.get(e);var o={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if("default"!==i&&Object.prototype.hasOwnProperty.call(e,i)){var l=r?Object.getOwnPropertyDescriptor(e,i):null;l&&(l.get||l.set)?Object.defineProperty(o,i,l):o[i]=e[i]}o.default=e,n&&n.set(e,o);return o}(n(87363)),l=r(n(93231)),c=r(n(40131));function _getRequireWildcardCache(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(_getRequireWildcardCache=function _getRequireWildcardCache(e){return e?n:t})(e)}function ownKeys(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function _objectSpread(e){for(var t=1;t