diff --git a/.changelogs/fix_unload-event-in-tracking.yml b/.changelogs/fix_unload-event-in-tracking.yml
new file mode 100644
index 0000000000..d72007e8a2
--- /dev/null
+++ b/.changelogs/fix_unload-event-in-tracking.yml
@@ -0,0 +1,5 @@
+significance: patch
+type: fixed
+links:
+ - "#2620"
+entry: Fixes Pagespeed notice regarding deprecated Javascript event usage.
diff --git a/.gitignore b/.gitignore
index 59ac4ca4db..140858a99a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,6 +27,7 @@ assets/css/lifterlms-rtl.css
assets/css/lifterlms-rtl.min.css
assets/css/lifterlms.css
assets/css/lifterlms.min.css
+assets/js/llms.js
assets/js/llms-builder.js
assets/js/llms-builder.min.js
assets/js/llms-admin-elementor-editor.js
diff --git a/assets/js/app/llms-tracking.js b/assets/js/app/llms-tracking.js
index 9997e29cc1..cbf7f772e2 100644
--- a/assets/js/app/llms-tracking.js
+++ b/assets/js/app/llms-tracking.js
@@ -35,7 +35,7 @@ LLMS.Tracking = function( settings ) {
self.addEvent( 'page.load' );
window.addEventListener( 'beforeunload', onBeforeUnload );
- window.addEventListener( 'unload', onUnload );
+ window.addEventListener( 'pagehide', onUnload );
document.addEventListener( 'visibilitychange', onVisibilityChange );
diff --git a/assets/js/llms.js b/assets/js/llms.js
deleted file mode 100644
index ffdd429296..0000000000
--- a/assets/js/llms.js
+++ /dev/null
@@ -1,2609 +0,0 @@
-/****************************************************************
- *
- * Contributor's Notice
- *
- * This is a compiled file and should not be edited directly!
- * The uncompiled script is located in the "assets/private" directory
- *
- ****************************************************************/
-
-/**
- * Main LLMS Namespace
- *
- * @since 1.0.0
- * @version 5.3.3
- */
-
-var LLMS = window.LLMS || {};
-( function( $ ){
-
- 'use strict';
-
- /**
- * Load all app modules
- */
- /**
- * Front End Achievements
- *
- * @package LifterLMS/Scripts
- *
- * @since 3.14.0
- * @version 6.10.2
- */
-
- LLMS.Achievements = {
-
- /**
- * Init
- *
- * @since 3.14.0
- * @since 4.5.1 Fix conditional loading check.
- *
- * @return {void}
- */
- init: function() {
-
- if ( $( '.llms-achievement' ).length ) {
-
- var self = this;
-
- $( function() {
- self.bind();
- self.maybe_open();
- } );
- }
-
- },
-
- /**
- * Bind DOM events
- *
- * @since 3.14.0
- *
- * @return {void}
- */
- bind: function() {
-
- var self = this;
-
- $( '.llms-achievement' ).each( function() {
-
- self.create_modal( $( this ) );
-
- } );
-
- $( '.llms-achievement' ).on( 'click', function() {
-
- var $this = $( this ),
- id = 'achievement-' + $this.attr( 'data-id' ),
- $modal = $( '#' + id );
-
- if ( ! $modal.length ) {
- self.create_modal( $this );
- }
-
- $modal.iziModal( 'open' );
-
- } );
-
- },
-
- /**
- * Creates modal a modal for an achievement
- *
- * @since 3.14.0
- *
- * @param obj $el The jQuery selector for the modal card.
- * @return {void}
- */
- create_modal: function( $el ) {
-
- var id = 'achievement-' + $el.attr( 'data-id' ),
- $modal = $( '#' + id );
-
- if ( ! $modal.length ) {
- $modal = $( '
' );
- $( 'body' ).append( $modal );
- }
-
- $modal.iziModal( {
- headerColor: '#3a3a3a',
- group: 'achievements',
- history: true,
- loop: true,
- overlayColor: 'rgba( 0, 0, 0, 0.6 )',
- transitionIn: 'fadeInDown',
- transitionOut: 'fadeOutDown',
- width: 340,
- onOpening: function( modal ) {
-
- modal.setTitle( $el.find( '.llms-achievement-title' ).html() );
- modal.setSubtitle( $el.find( '.llms-achievement-date' ).html() );
- modal.setContent( '' + $el.html() + '
' );
-
- },
-
- onClosing: function() {
- window.history.pushState( '', document.title, window.location.pathname + window.location.search );
- },
-
- } );
-
- },
-
- /**
- * On page load, opens a modal if the URL contains an achievement in the location hash
- *
- * @since 3.14.0
- * @since 6.10.2 Sanitize achievement IDs before using window.location.hash to trigger the modal open.
- *
- * @return {void}
- */
- maybe_open: function() {
-
- let hash = window.location.hash.split( '-' );
- if ( 2 !== hash.length ) {
- return;
- }
-
- hash[1] = parseInt( hash[1] );
- if ( '#achievement-' !== hash[0] || ! Number.isInteger( hash[1] ) ) {
- return;
- }
-
- const a = document.querySelector( `a[href="${ hash.join( '-' ) }"]` )
- if ( ! a ) {
- return;
- }
-
- a.click();
-
- }
-
- };
-
- /**
- * Main Ajax class
- * Handles Primary Ajax connection
- *
- * @package LifterLMS/Scripts
- *
- * @since Unknown
- * @version Unknown
- */
-
- LLMS.Ajax = {
-
- /**
- * Url
- *
- * @type {String}
- */
- url: window.ajaxurl || window.llms.ajaxurl,
-
- /**
- * Type
- *
- * @type {[type]}
- */
- type: 'post',
-
- /**
- * Data
- *
- * @type {[type]}
- */
- data: [],
-
- /**
- * Cache
- *
- * @type {[type]}
- */
- cache: false,
-
- /**
- * DataType
- * defaulted to json
- *
- * @type {String}
- */
- dataType: 'json',
-
- /**
- * Async
- * default to false
- *
- * @type {Boolean}
- */
- async: true,
-
- response:[],
-
- /**
- * Initialize Ajax methods
- *
- * @since Unknown
- * @since 4.4.0 Update ajax nonce source.
- *
- * @param {Object} obj Options object.
- * @return {Object}
- */
- init: function( obj ) {
-
- // If obj is not of type object or null return false.
- if ( obj === null || typeof obj !== 'object' ) {
- return false;
- }
-
- // set object defaults if values are not supplied
- obj.url = 'url' in obj ? obj.url : this.url;
- obj.type = 'type' in obj ? obj.type : this.type;
- obj.data = 'data' in obj ? obj.data : this.data;
- obj.cache = 'cache' in obj ? obj.cache : this.cache;
- obj.dataType = 'dataType' in obj ? obj.dataType : this.dataType;
- obj.async = 'async' in obj ? obj.async : this.async;
-
- // Add nonce to data object.
- obj.data._ajax_nonce = window.llms.ajax_nonce || wp_ajax_data.nonce;
-
- // Add post id to data object.
- var $R = LLMS.Rest,
- query_vars = $R.get_query_vars();
- obj.data.post_id = 'post' in query_vars ? query_vars.post : null;
- if ( ! obj.data.post_id && $( 'input#post_ID' ).length ) {
- obj.data.post_id = $( 'input#post_ID' ).val();
- }
-
- return obj;
- },
-
- /**
- * Call
- * Called by external classes
- * Sets up jQuery Ajax object
- *
- * @param {[object]} [object of ajax settings]
- * @return {[mixed]} [false if not object or this]
- */
- call: function(obj) {
-
- // get default variables if not included in call
- var settings = this.init( obj );
-
- // if init return a response of false
- if ( ! settings) {
- return false;
- } else {
- this.request( settings );
- }
-
- return this;
-
- },
-
- /**
- * Calls jQuery Ajax on settings object
- *
- * @return {[object]} [this]
- */
- request: function(settings) {
-
- $.ajax( settings );
-
- return this;
-
- }
-
- };
-
- /**
- * Create a Donut Chart
- *
- * @package LifterLMS/Scripts
- *
- * @since 3.9.0
- * @version 4.15.0
- *
- * @link https://gist.github.com/joeyinbox/8205962
- *
- * @param {Object} $el jQuery element to draw a chart within.
- */
-
- LLMS.Donut = function( $el ) {
-
- /**
- * Constructor
- *
- * @since 3.9.0
- * @since 4.15.0 Flip animation in RTL.
- *
- * @param {Object} options Donut options.
- * @return {Void}
- */
- function Donut(options) {
-
- this.settings = $.extend( {
- element: options.element,
- percent: 100
- }, options );
-
- this.circle = this.settings.element.find( 'path' );
- this.settings.stroke_width = parseInt( this.circle.css( 'stroke-width' ) );
- this.radius = ( parseInt( this.settings.element.css( 'width' ) ) - this.settings.stroke_width ) / 2;
- this.angle = $( 'body' ).hasClass( 'rtl' ) ? 82.5 : 97.5; // Origin of the draw at the top of the circle
- this.i = Math.round( 0.75 * this.settings.percent );
- this.first = true;
- this.increment = $( 'body' ).hasClass( 'rtl' ) ? -5 : 5;
-
- this.animate = function() {
- this.timer = setInterval( this.loop.bind( this ), 10 );
- };
-
- this.loop = function() {
- this.angle += this.increment;
- this.angle %= 360;
- var radians = ( this.angle / 180 ) * Math.PI,
- x = this.radius + this.settings.stroke_width / 2 + Math.cos( radians ) * this.radius,
- y = this.radius + this.settings.stroke_width / 2 + Math.sin( radians ) * this.radius,
- d;
- if (this.first === true) {
- d = this.circle.attr( 'd' ) + ' M ' + x + ' ' + y;
- this.first = false;
- } else {
- d = this.circle.attr( 'd' ) + ' L ' + x + ' ' + y;
- }
- this.circle.attr( 'd', d );
- this.i--;
-
- if (this.i <= 0) {
- clearInterval( this.timer );
- }
- };
- }
-
- /**
- * Draw donut element
- *
- * @since 3.9.0
- *
- * @param {Object} $el jQuery element to draw a chart within.
- * @return {Void}
- */
- function draw( $el ) {
- var path = '';
- $el.append( '' );
- var donut = new Donut( {
- element: $el,
- percent: $el.attr( 'data-perc' )
- } );
- donut.animate();
- }
-
- draw( $el );
-
- };
-
- /**
- * Forms
- *
- * @package LifterLMS/Scripts
- *
- * @since 5.0.0
- * @version 7.0.0
- */
-
- LLMS.Forms = {
-
- /**
- * Stores locale information.
- *
- * Added via PHP.
- *
- * @type {Object}
- */
- address_info: {},
-
- /**
- * jQuery ref. to the city text field.
- *
- * @type {Object}
- */
- $cities: null,
-
- /**
- * jQuery ref. to the countries select field.
- *
- * @type {Object}
- */
- $countries: null,
-
- /**
- * jQuery ref. to the states select field.
- *
- * @type {Object}
- */
- $states: null,
-
- /**
- * jQuery ref. to the hidden states holder field.
- *
- * @type {Object}
- */
- $states_holder: null,
-
- /**
- * Init
- *
- * @since 5.0.0
- * @since 5.3.3 Move select2 dependency check into the `bind_l10_selects()` method.
- *
- * @return {void}
- */
- init: function() {
-
- if ( $( 'body' ).hasClass( 'wp-admin' ) ) {
- if ( ! ( $( 'body' ).hasClass( 'profile-php' ) || $( 'body' ).hasClass( 'user-edit-php' ) ) ) {
- return;
- }
- }
-
- var self = this;
-
- self.bind_matching_fields();
- self.bind_voucher_field();
- self.bind_edit_account();
- self.bind_l10n_selects();
-
- },
-
- /**
- * Bind DOM events for the edit account screen.
- *
- * @since 5.0.0
- *
- * @return {void}
- */
- bind_edit_account: function() {
-
- // Not an edit account form.
- if ( ! $( 'form.llms-person-form.edit-account' ).length ) {
- return;
- }
-
- $( '.llms-toggle-fields' ).on( 'click', this.handle_toggle_click );
-
- },
-
- /**
- * Bind DOM Events fields with dynamic localization values and language.
- *
- * @since 5.0.0
- * @since 5.3.3 Bind select2-related events after ensuring select2 is available.
- *
- * @return {void}
- */
- bind_l10n_selects: function() {
-
- var self = this;
-
- self.$cities = $( '#llms_billing_city' );
- self.$countries = $( '.llms-l10n-country-select select' );
- self.$states = $( '.llms-l10n-state-select select' );
- self.$zips = $( '#llms_billing_zip' );
-
- if ( ! self.$countries.length ) {
- return;
- }
-
- var isSelect2Available = function() {
- return ( undefined !== $.fn.llmsSelect2 );
- };
-
- LLMS.wait_for( isSelect2Available, function() {
-
- if ( self.$states.length ) {
- self.prep_state_field();
- }
-
- self.$countries.add( self.$states ).llmsSelect2( { width: '100%' } );
-
- if ( window.llms.address_info ) {
- self.address_info = JSON.parse( window.llms.address_info );
- }
-
- self.$countries.on( 'change', function() {
-
- var val = $( this ).val();
- self.update_locale_info( val );
-
- } ).trigger( 'change' );
-
- }, 'llmsSelect2' );
-
- },
-
- /**
- * Ensure "matching" fields match.
- *
- * @since 5.0.0
- *
- * @return {Void}
- */
- bind_matching_fields: function() {
-
- var $fields = $( 'input[data-match]' ).not( '[type="password"]' );
-
- $fields.each( function() {
-
- var $field = $( this ),
- $match = $( '#' + $field.attr( 'data-match' ) ),
- $parents;
-
- if ( $match.length ) {
-
- $parents = $field.closest( '.llms-form-field' ).add( $match.closest( '.llms-form-field' ) );
-
- $field.on( 'input change', function() {
-
- var val_1 = $field.val(),
- val_2 = $match.val();
-
- if ( val_1 && val_2 && val_1 !== val_2 ) {
- $parents.addClass( 'invalid' );
- } else {
- $parents.removeClass( 'invalid' );
- }
-
- } );
-
- }
-
- } );
-
- },
-
- /**
- * Bind DOM events for voucher toggles UX.
- *
- * @since 5.0.0
- *
- * @return {void}
- */
- bind_voucher_field: function() {
-
- $( '#llms-voucher-toggle' ).on( 'click', function( e ) {
- e.preventDefault();
- $( '#llms_voucher' ).toggle();
- } );
-
- },
-
- /**
- * Retrieve the parent element for a given field.
- *
- * The parent element is hidden when the field isn't required.
- *
- * @since 5.0.0
- * @since 7.0.0 Do not look for a WP column wrapper anymore, always return the field's wrapper div.
- *
- * @param {Object} $field jQuery dom object.
- * @return {Object}
- */
- get_field_parent: function( $field ) {
-
- return $field.closest( '.llms-form-field' );
-
- },
-
- /**
- * Retrieve the text of a label
- *
- * Removes any children HTML elements (eg: required span elements) and returns only the labels text.
- *
- * @since 5.0.0
- *
- * @param {Object} $label jQuery object for a label element.
- * @return {String}
- */
- get_label_text: function( $label ) {
-
- var $clone = $label.clone();
- $clone.find( '*' ).remove();
- return $clone.text().trim();
-
- },
-
- /**
- * Callback function to handle the "toggle" button links for changing email address and password on account edit forms
- *
- * @since 5.0.0
- *
- * @param {Object} event Native JS event object.
- * @return {void}
- */
- handle_toggle_click: function( event ) {
-
- event.preventDefault();
-
- var $this = $( this ),
- $fields = $( $( this ).attr( 'data-fields' ) ),
- isShowing = $this.attr( 'data-is-showing' ) || 'no',
- displayFunc = 'yes' === isShowing ? 'hide' : 'show',
- disabled = 'yes' === isShowing ? 'disabled' : null,
- textAttr = 'yes' === isShowing ? 'data-change-text' : 'data-cancel-text';
-
- $fields.each( function() {
-
- $( this ).closest( '.llms-form-field' )[ displayFunc ]();
- $( this ).attr( 'disabled', disabled );
-
- } );
-
- $this.text( $this.attr( textAttr ) );
- $this.attr( 'data-is-showing', 'yes' === isShowing ? 'no' : 'yes' );
-
- },
-
- /**
- * Prepares the state select field.
- *
- * Moves All optgroup elements into a hidden & disabled select element.
- *
- * @since 5.0.0
- *
- * @return {void}
- */
- prep_state_field: function() {
-
- var $parent = this.$states.closest( '.llms-form-field' );
-
- this.$holder = $( '' );
-
- this.$holder.appendTo( $parent );
- this.$states.find( 'optgroup' ).appendTo( this.$holder );
-
- },
-
- /**
- * Updates the text of a label for a given field.
- *
- * @since 5.0.0
- *
- * @param {Object} $field jQuery object of the form field.
- * @param {String} text Label text.
- * @return {void}
- */
- update_label: function( $field, text ) {
-
- var $label = this.get_field_parent( $field ).find( 'label' ),
- $required = $label.find( '.llms-required' ).clone();
-
- $label.html( text );
- $label.append( $required );
-
- },
-
- /**
- * Update form fields based on selected country
- *
- * Replaces label text with locale-specific language and
- * hides or shows zip fields based on whether or not
- * they are required for the given country.
- *
- * @since 5.0.0
- *
- * @param {String} country_code Currently selected country code.
- * @return {void}
- */
- update_locale_info: function( country_code ) {
-
- if ( ! this.address_info || ! this.address_info[ country_code ] ) {
- return;
- }
-
- var info = this.address_info[ country_code ];
-
- this.update_state_options( country_code );
- this.update_label( this.$states, info.state );
-
- this.update_locale_info_for_field( this.$cities, info.city );
- this.update_locale_info_for_field( this.$zips, info.postcode );
-
- },
-
- /**
- * Update locale info for a given field.
- *
- * @since 5.0.0
- *
- * @param {Object} $field The jQuery object for the field.
- * @param {String|Boolean} label The text of the label, or `false` when the field isn't supported.
- * @return {Void}
- */
- update_locale_info_for_field: function( $field, label ) {
-
- if ( label ) {
- this.update_label( $field, label );
- this.enable_field( $field );
- } else {
- this.disable_field( $field );
- }
-
- },
-
- /**
- * Update the available options in the state field
- *
- * Removes existing options and copies the options
- * for the requested country from the hidden select field.
- *
- * If there are no states for the given country the state
- * field will be hidden.
- *
- * @since 5.0.0
- *
- * @param {String} country_code Currently selected country code.
- * @return {void}
- */
- update_state_options: function( country_code ) {
-
- if ( ! this.$states.length ) {
- return;
- }
-
- var opts = this.$holder.find( 'optgroup[data-key="' + country_code + '"] option' ).clone();
-
- if ( ! opts.length ) {
- this.$states.html( '' );
- this.disable_field( this.$states );
- } else {
- this.enable_field( this.$states );
- this.$states.html( opts );
- }
-
- },
-
- /**
- * Disable a given field
- *
- * It also hides the parent element, and adds an empty hidden input field
- * with the same 'name' as teh being disabled field so to be sure to clear the field.
- *
- * @since 5.0.0
- *
- * @param {Object} $field The jQuery object for the field.
- */
- disable_field: function( $field ) {
- $(
- '',
- { name: $field.attr('name'), class: $field.attr( 'class' ) + ' hidden', type: 'hidden' }
- ).insertAfter( $field );
- $field.attr( 'disabled', 'disabled' );
- this.get_field_parent( $field ).hide();
- },
-
- /**
- * Enable a given field
- *
- * It also shows the parent element, and removes the empty hidden input field
- * previously added by disable_field().
- *
- * @since 5.0.0
- *
- * @param {Object} $field The jQuery object for the field.
- */
- enable_field: function( $field ) {
- $field.removeAttr( 'disabled' );
- $field.next( '.hidden[name='+$field.attr('name')+']' ).detach();
- this.get_field_parent( $field ).show();
- }
-
- };
-
- /**
- * Instructors List
- *
- * @package LifterLMS/Scripts
- *
- * @since Unknown
- * @version Unknown
- */
-
- LLMS.Instructors = {
-
- /**
- * Init
- */
- init: function() {
-
- var self = this;
-
- if ( $( 'body' ).hasClass( 'wp-admin' ) ) {
- return;
- }
-
- if ( $( '.llms-instructors' ).length ) {
-
- LLMS.wait_for_matchHeight( function() {
- self.bind();
- } );
-
- }
-
- },
-
- /**
- * Bind Method
- * Handles dom binding on load
- *
- * @return {[type]} [description]
- */
- bind: function() {
-
- $( '.llms-instructors .llms-author' ).matchHeight();
-
- },
-
- };
-
- /**
- * Localization functions for LifterLMS Javascript
- *
- * @package LifterLMS/Scripts
- *
- * @since 2.7.3
- * @version 2.7.3
- *
- * @todo we need more robust translation functions to handle sprintf and pluralization
- * at this moment we don't need those and haven't stubbed them out
- * those will be added when they're needed
- */
-
- LLMS.l10n = LLMS.l10n || {};
-
- LLMS.l10n.translate = function ( string ) {
-
- var self = this;
-
- if ( self.strings[string] ) {
-
- return self.strings[string];
-
- } else {
-
- return string;
-
- }
-
- };
-
- /**
- * Translate and replace placeholders in a string
- *
- * @example LLMS.l10n.replace( 'This is a %2$s %1$s String', {
- * '%1$s': 'cool',
- * '%2$s': 'very'
- * } );
- * Output: "This is a very cool String"
- *
- * @param string string text string
- * @param object replacements object containing token => replacement pairs
- * @return string
- * @since 3.16.0
- * @version 3.16.0
- */
- LLMS.l10n.replace = function( string, replacements ) {
-
- var str = this.translate( string );
-
- $.each( replacements, function( token, value ) {
-
- if ( -1 !== token.indexOf( 's' ) ) {
- value = value.toString();
- } else if ( -1 !== token.indexOf( 'd' ) ) {
- value = value * 1;
- }
-
- str = str.replace( token, value );
-
- } );
-
- return str;
-
- };
-
- /**
- * Handle Lesson Preview Elements
- *
- * @package LifterLMS/Scripts
- *
- * @since 3.0.0
- * @version 3.16.12
- */
-
- LLMS.LessonPreview = {
-
- /**
- * A jQuery object of all outlines present on the current screen
- *
- * @type obj
- */
- $els: null,
-
- /**
- * Initialize
- *
- * @return void
- */
- init: function() {
-
- var self = this;
-
- this.$locked = $( 'a[href="#llms-lesson-locked"]' );
-
- if ( this.$locked.length ) {
-
- self.bind();
-
- }
-
- if ( $( '.llms-course-navigation' ).length ) {
-
- LLMS.wait_for_matchHeight( function() {
-
- self.match_height();
-
- } );
-
- }
-
- },
-
- /**
- * Bind DOM events
- *
- * @return void
- * @since 3.0.0
- * @version 3.16.12
- */
- bind: function() {
-
- var self = this;
-
- this.$locked.on( 'click', function() {
- return false;
- } );
-
- this.$locked.on( 'mouseenter', function() {
-
- var $tip = $( this ).find( '.llms-tooltip' );
- if ( ! $tip.length ) {
- var msg = $( this ).attr( 'data-tooltip-msg' );
- if ( ! msg ) {
- msg = LLMS.l10n.translate( 'You do not have permission to access this content' );
- }
- $tip = self.get_tooltip( msg );
- $( this ).append( $tip );
- }
- setTimeout( function() {
- $tip.addClass( 'show' );
- }, 10 );
-
- } );
-
- this.$locked.on( 'mouseleave', function() {
-
- var $tip = $( this ).find( '.llms-tooltip' );
- $tip.removeClass( 'show' );
-
- } );
-
- },
-
- /**
- * Match the height of lesson preview items in course navigation blocks
- *
- * @return void
- * @since 3.0.0
- * @version 3.0.0
- */
- match_height: function() {
-
- $( '.llms-course-navigation .llms-lesson-link' ).matchHeight();
-
- },
-
- /**
- * Get a tooltip element
- *
- * @param string msg message to display inside the tooltip
- * @return obj
- * @since 3.0.0
- * @version 3.2.4
- */
- get_tooltip: function( msg ) {
- var $el = $( '' );
- $el.append( '' + msg + '
' );
- return $el;
- },
-
- };
-
- /**
- * LifterLMS Loops JS
- *
- * @package LifterLMS/Scripts
- *
- * @since 3.0.0
- * @version 3.14.0
- */
-
- LLMS.Loops = {
-
- /**
- * Initialize
- *
- * @return void
- */
- init: function() {
-
- var self = this;
-
- if ( $( '.llms-loop' ).length ) {
-
- LLMS.wait_for_matchHeight( function() {
-
- self.match_height();
-
- } );
-
- }
-
- },
-
- /**
- * Match the height of .llms-loop-item
- *
- * @return void
- * @since 3.0.0
- * @version 3.14.0
- */
- match_height: function() {
-
- $( '.llms-loop-item .llms-loop-item-content' ).matchHeight();
- $( '.llms-achievement-loop-item .llms-achievement' ).matchHeight();
- $( '.llms-certificate-loop-item .llms-certificate' ).matchHeight();
-
- },
-
- };
-
- /**
- * Handle the Collapsible Syllabus Widget / Shortcode
- *
- * @package LifterLMS/Scripts
- *
- * @since Unknown
- * @version Unknown
- */
-
- LLMS.OutlineCollapse = {
-
- /**
- * A jQuery object of all outlines present on the current screen
- *
- * @type obj
- */
- $outlines: null,
-
- /**
- * Initialize
- *
- * @return void
- */
- init: function() {
-
- this.$outlines = $( '.llms-widget-syllabus--collapsible' );
-
- if ( this.$outlines.length ) {
-
- this.bind();
-
- }
-
- },
-
- /**
- * Bind DOM events
- *
- * @return void
- */
- bind: function() {
-
- var self = this;
-
- this.$outlines.each( function() {
-
- var $outline = $( this ),
- $headers = $outline.find( '.llms-section .section-header' );
-
- // bind header clicks
- $headers.on( 'click', function( e ) {
-
- e.preventDefault();
-
- var $toggle = $( this ),
- $section = $toggle.closest( '.llms-section' ),
- state = self.get_section_state( $section );
-
- switch ( state ) {
-
- case 'closed':
- self.open_section( $section );
- break;
-
- case 'opened':
- self.close_section( $section );
- break;
-
- }
-
- } );
-
- // bind optional toggle "buttons"
- $outline.find( '.llms-collapse-toggle' ).on( 'click', function( e ) {
-
- e.preventDefault();
-
- var $btn = $( this ),
- action = $btn.attr( 'data-action' ),
- opposite_action = ( 'close' === action ) ? 'opened' : 'closed';
-
- $headers.each( function() {
-
- var $section = $( this ).closest( '.llms-section' ),
- state = self.get_section_state( $section );
-
- if ( opposite_action !== state ) {
- return true;
- }
-
- switch ( state ) {
-
- case 'closed':
- self.close_section( $section );
- break;
-
- case 'opened':
- self.open_section( $section );
- break;
-
- }
-
- $( this ).trigger( 'click' );
-
- } );
-
- } );
-
- } );
-
- },
-
- /**
- * Close an outline section
- *
- * @param obj $section jQuery selector of a '.llms-section'
- * @return void
- */
- close_section: function( $section ) {
-
- $section.removeClass( 'llms-section--opened' ).addClass( 'llms-section--closed' );
-
- },
-
- /**
- * Open an outline section
- *
- * @param obj $section jQuery selector of a '.llms-section'
- * @return void
- */
- open_section: function( $section ) {
-
- $section.removeClass( 'llms-section--closed' ).addClass( 'llms-section--opened' );
-
- },
-
- /**
- * Get the current state (open or closed) of an outline section
- *
- * @param obj $section jQuery selector of a '.llms-section'
- * @return string 'opened' or 'closed'
- */
- get_section_state: function( $section ) {
-
- return $section.hasClass( 'llms-section--opened' ) ? 'opened' : 'closed';
-
- }
-
- };
-
- /**
- * Handle Password Strength Meter for registration and password update fields
- *
- * @package LifterLMS/Scripts
- *
- * @since 3.0.0
- * @version 5.0.0
- */
-
- $.extend( LLMS.PasswordStrength, {
-
- /**
- * jQuery ref for the password strength meter object.
- *
- * @type {Object}
- */
- $meter: $( '.llms-password-strength-meter' ),
-
- /**
- * jQuery ref for the password field.
- *
- * @type {Object}
- */
- $pass: null,
-
- /**
- * jQuery ref for the password confirmation field
- *
- * @type {Object}
- */
- $conf: null,
-
- /**
- * jQuery ref for form element.
- *
- * @type {Object}
- */
- $form: null,
-
- /**
- * Init
- * loads class methods
- *
- * @since 3.0.0
- * @since 3.7.0 Unknown
- * @since 5.0.0 Move reference setup to `setup_references()`.
- * Use `LLMS.wait_for()` for dependency waiting.
- *
- * @return {Void}
- */
- init: function() {
-
- if ( $( 'body' ).hasClass( 'wp-admin' ) ) {
- return;
- }
-
- if ( ! this.setup_references() ) {
- return;
- }
-
- var self = this;
-
- LLMS.wait_for( function() {
- return ( 'undefined' !== typeof wp && 'undefined' !== typeof wp.passwordStrength );
- }, function() {
- self.bind();
- self.$form.trigger( 'llms-password-strength-ready' );
- } );
-
- },
-
- /**
- * Bind DOM Events
- *
- * @since 3.0.0
- *
- * @return void
- */
- bind: function() {
-
- var self = this;
-
- // add submission event handlers when not on a checkout form
- if ( ! this.$form.hasClass( 'llms-checkout' ) ) {
- self.$form.on( 'submit', self, self.submit );
- }
-
- // check password strength on keyup
- self.$pass.add( self.$conf ).on( 'keyup', function() {
- self.check_strength();
- } );
-
- },
-
- /**
- * Check the strength of a user entered password
- * and update elements depending on the current strength
- *
- * @since 3.0.0
- * @since 5.0.0 Allow password confirmation to be optional when checking strength.
- *
- * @return void
- */
- check_strength: function() {
-
- var $pass_field = this.$pass.closest( '.llms-form-field' ),
- $conf_field = this.$conf && this.$conf.length ? this.$conf.closest( '.llms-form-field' ) : null,
- pass_length = this.$pass.val().length,
- conf_length = this.$conf && this.$conf.length ? this.$conf.val().length : 0;
-
- // hide the meter if both fields are empty
- if ( ! pass_length && ! conf_length ) {
- $pass_field.removeClass( 'valid invalid' );
- if ( $conf_field ) {
- $conf_field.removeClass( 'valid invalid' );
- }
- this.$meter.hide();
- return;
- }
-
- if ( this.get_current_strength_status() ) {
- $pass_field.removeClass( 'invalid' ).addClass( 'valid' );
- if ( conf_length ) {
- $conf_field.removeClass( 'invalid' ).addClass( 'valid' );
- }
- } else {
- $pass_field.removeClass( 'valid' ).addClass( 'invalid' );
- if ( conf_length ) {
- $conf_field.removeClass( 'valid' ).addClass( 'invalid' );
- }
- }
-
- this.$meter.removeClass( 'too-short very-weak weak medium strong mismatch' );
- this.$meter.show().addClass( this.get_current_strength( 'slug' ) );
- this.$meter.html( this.get_current_strength( 'text' ) );
-
- },
-
- /**
- * Form submission action called during registration on checkout screen
- *
- * @since 3.0.0
- *
- * @param obj self instance of this class
- * @param Function callback callback function, passes error message or success back to checkout handler
- * @return void
- */
- checkout: function( self, callback ) {
-
- if ( self.get_current_strength_status() ) {
-
- callback( true );
-
- } else {
-
- callback( LLMS.l10n.translate( 'There is an issue with your chosen password.' ) );
-
- }
- },
-
- /**
- * Get the list of blocklisted strings
- *
- * @since 5.0.0
- *
- * @return array
- */
- get_blocklist: function() {
-
- // Default values from WP Core + any values added via settings filter..
- var blocklist = wp.passwordStrength.userInputDisallowedList().concat( this.get_setting( 'blocklist', [] ) );
-
- // Add values from all text fields in the form.
- this.$form.find( 'input[type="text"], input[type="email"], input[type="tel"], input[type="number"]' ).each( function() {
- var val = $( this ).val();
- if ( val ) {
- blocklist.push( val );
- }
- } );
-
- return blocklist;
-
- },
-
- /**
- * Retrieve current strength as a number, a slug, or a translated text string
- *
- * @since 3.0.0
- * @since 5.0.0 Allow password confirmation to be optional when checking strength.
- *
- * @param {String} format Derived return format [int|slug|text] defaults to int.
- * @return mixed
- */
- get_current_strength: function( format ) {
-
- format = format || 'int';
- var pass = this.$pass.val(),
- conf = this.$conf && this.$conf.length ? this.$conf.val() : '',
- val;
-
- // enforce custom length requirement
- if ( pass.length < this.get_setting( 'min_length', 6 ) ) {
- val = -1;
- } else {
- val = wp.passwordStrength.meter( pass, this.get_blocklist(), conf );
- // 0 & 1 are both very-weak
- if ( 0 === val ) {
- val = 1;
- }
- }
-
- if ( 'slug' === format ) {
- return this.get_strength_slug( val );
- } else if ( 'text' === format ) {
- return this.get_strength_text( val );
- } else {
- return val;
- }
- },
-
- /**
- * Determines if the current password strength meets the user-defined
- * minimum password strength requirements
- *
- * @since 3.0.0
- *
- * @return boolean
- */
- get_current_strength_status: function() {
- var curr = this.get_current_strength(),
- min = this.get_strength_value( this.get_minimum_strength() );
- return ( 5 === curr ) ? false : ( curr >= min );
- },
-
- /**
- * Retrieve the minimum password strength for the current form.
- *
- * @since 3.0.0
- * @since 5.0.0 Replaces the version output via an inline PHP script in favor of utilizing values configured in the settings object.
- *
- * @return {string}
- */
- get_minimum_strength: function() {
- return this.get_setting( 'min_strength', 'strong' );
- },
-
- /**
- * Get a setting and fallback to a default value.
- *
- * @since 5.0.0
- *
- * @param {String} key Setting key.
- * @param {mixed} default_val Default value when the requested setting cannot be located.
- * @return {mixed}
- */
- get_setting: function( key, default_val ) {
- var settings = this.get_settings();
- return settings[ key ] ? settings[ key ] : default_val;
- },
-
- /**
- * Get the slug associated with a strength value
- *
- * @since 3.0.0
- *
- * @param int strength_val Strength value number.
- * @return string
- */
- get_strength_slug: function( strength_val ) {
-
- var slugs = {
- '-1': 'too-short',
- 1: 'very-weak',
- 2: 'weak',
- 3: 'medium',
- 4: 'strong',
- 5: 'mismatch',
- };
-
- return ( slugs[ strength_val ] ) ? slugs[ strength_val ] : slugs[5];
-
- },
-
- /**
- * Gets the translated text associated with a strength value
- *
- * @since 3.0.0
- *
- * @param {Integer} strength_val Strength value
- * @return {String}
- */
- get_strength_text: function( strength_val ) {
-
- var texts = {
- '-1': LLMS.l10n.translate( 'Too Short' ),
- 1: LLMS.l10n.translate( 'Very Weak' ),
- 2: LLMS.l10n.translate( 'Weak' ),
- 3: LLMS.l10n.translate( 'Medium' ),
- 4: LLMS.l10n.translate( 'Strong' ),
- 5: LLMS.l10n.translate( 'Mismatch' ),
- };
-
- return ( texts[ strength_val ] ) ? texts[ strength_val ] : texts[5];
-
- },
-
- /**
- * Get the value associated with a strength slug
- *
- * @since 3.0.0
- *
- * @param string strength_slug A strength slug.
- * @return {Integer}
- */
- get_strength_value: function( strength_slug ) {
-
- var values = {
- 'too-short': -1,
- 'very-weak': 1,
- weak: 2,
- medium: 3,
- strong: 4,
- mismatch: 5,
- };
-
- return ( values[ strength_slug ] ) ? values[ strength_slug ] : values.mismatch;
-
- },
-
- /**
- * Setup jQuery references to DOM elements needed to power the password meter.
- *
- * @since 5.0.0
- *
- * @return {Boolean} Returns `true` if a meter element and password field are found, otherwise returns `false`.
- */
- setup_references: function() {
-
- if ( ! this.$meter.length ) {
- return false;
- }
-
- this.$form = this.$meter.closest( 'form' );
- this.$pass = this.$form.find( 'input#password' );
-
- if ( this.$pass.length && this.$pass.attr( 'data-match' ) ) {
- this.$conf = this.$form.find( '#' + this.$pass.attr( 'data-match' ) );
- }
-
- return ( this.$pass.length > 0 );
-
- },
-
- /**
- * Form submission handler for registration and update forms
- *
- * @since 3.0.0
- * @since 5.0.0 Allow the account edit for to bypass strength checking when the password field is disabled (not being submitted).
- *
- * @param obj e Event data.
- * @return void
- */
- submit: function( e ) {
-
- var self = e.data;
- e.preventDefault();
- self.$pass.trigger( 'keyup' );
-
- // Meets the status requirements OR we're on the account edit form and the password field is disabled.
- if ( self.get_current_strength_status() || ( self.$form.hasClass( 'edit-account' ) && 'disabled' === self.$pass.attr( 'disabled' ) ) ) {
- self.$form.off( 'submit', self.submit );
- self.$form.trigger( 'submit' );
- } else {
- $( 'html, body' ).animate( {
- scrollTop: self.$meter.offset().top - 100,
- }, 200 );
- self.$meter.hide();
- setTimeout( function() {
- self.$meter.fadeIn( 400 );
- }, 220 );
- }
- },
-
- /**
- * Get the list of blocklist strings
- *
- * @since 3.0.0
- * @deprecated 5.0.0 `LLMS.PasswordStrength.get_blacklist()` is deprecated in favor of `LLMS.PasswordStrength.get_blocklist()`.
- *
- * @return array
- */
- get_blacklist: function() {
- console.log( 'Method `get_blacklist()` is deprecated in favor of `get_blocklist()`.' );
- return this.get_blacklist();
- },
-
- } );
-
- /**
- * Pricing Table UI
- *
- * @package LifterLMS/Scripts
- *
- * @since Unknown.
- * @version Unknown.
- */
-
- LLMS.Pricing_Tables = {
-
- /**
- * Init
- */
- init: function() {
-
- var self = this;
-
- if ( $( 'body' ).hasClass( 'wp-admin' ) ) {
- return;
- }
-
- if ( $( '.llms-access-plans' ).length ) {
-
- LLMS.wait_for_matchHeight( function() {
- self.bind();
- } );
-
- this.$locked = $( 'a[href="#llms-plan-locked"]' );
-
- if ( this.$locked.length ) {
-
- LLMS.wait_for_popover( function() {
- self.bind_locked();
- } );
-
- }
-
- }
-
- },
-
- /**
- * Bind Method
- * Handles dom binding on load
- *
- * @return {[type]} [description]
- */
- bind: function() {
-
- $( '.llms-access-plan-content' ).matchHeight();
- $( '.llms-access-plan-pricing.trial' ).matchHeight();
-
- },
-
- /**
- * Setup a popover for members-only restricted plans
- *
- * @return void
- * @since 3.0.0
- * @version 3.9.1
- */
- bind_locked: function() {
-
- this.$locked.each( function() {
-
- $( this ).webuiPopover( {
- animation: 'pop',
- closeable: true,
- content: function( e ) {
- var $content = $( '' );
- $content.append( e.$element.closest( '.llms-access-plan' ).find( '.llms-access-plan-restrictions ul' ).clone() );
- return $content;
- },
- placement: 'top',
- style: 'inverse',
- title: LLMS.l10n.translate( 'Members Only Pricing' ),
- width: '280px',
- } );
-
- } );
-
- },
-
- };
-
- /**
- * Quiz Attempt
- *
- * @package LifterLMS/Scripts
- *
- * @since 7.3.0
- * @version 7.3.0
- */
-
- LLMS.Quiz_Attempt = {
- /**
- * Initialize
- *
- * @return void
- */
- init: function() {
-
- $( '.llms-quiz-attempt-question-header a.toggle-answer' ).on( 'click', function( e ) {
-
- e.preventDefault();
-
- var $curr = $( this ).closest( 'header' ).next( '.llms-quiz-attempt-question-main' );
-
- $( this ).closest( 'li' ).siblings().find( '.llms-quiz-attempt-question-main' ).slideUp( 200 );
-
- if ( $curr.is( ':visible' ) ) {
- $curr.slideUp( 200 );
- } else {
- $curr.slideDown( 200 );
- }
-
- } );
- }
-
- }
-
- /**
- * LifterLMS Reviews JS
- *
- * @package LifterLMS/Scripts
- *
- * @since Unknown
- * @version Unknown
- */
-
- LLMS.Review = {
- /**
- * Init
- * loads class methods
- */
- init: function() {
- // console.log('Initializing Review ');
- this.bind();
- },
-
- /**
- * This function binds actions to the appropriate hooks
- */
- bind: function() {
- $( '#llms_review_submit_button' ).click(function()
- {
- if ($( '#review_title' ).val() !== '' && $( '#review_text' ).val() !== '') {
- jQuery.ajax({
- type : 'post',
- dataType : 'json',
- url : window.llms.ajaxurl,
- data : {
- action : 'LLMSSubmitReview',
- review_title: $( '#review_title' ).val(),
- review_text: $( '#review_text' ).val(),
- pageID : $( '#post_ID' ).val(),
- llms_review_nonce: $( '#llms_review_nonce' ).val()
- },
- success: function()
- {
- console.log( 'Review success' );
- $( '#review_box' ).hide( 'swing' );
- $( '#thank_you_box' ).show( 'swing' );
- },
- error: function(jqXHR, textStatus, errorThrown )
- {
- console.log( jqXHR );
- console.log( textStatus );
- console.log( errorThrown );
- },
- });
- } else {
- if ($( '#review_title' ).val() === '') {
- $( '#review_title_error' ).show( 'swing' );
- } else {
- $( '#review_title_error' ).hide( 'swing' );
- }
- if ($( '#review_text' ).val() === '') {
- $( '#review_text_error' ).show( 'swing' );
- } else {
- $( '#review_text_error' ).hide( 'swing' );
- }
- }
- });
- if ( $( '#_llms_display_reviews' ).attr( 'checked' ) ) {
- $( '.llms-num-reviews-top' ).addClass( 'top' );
- $( '.llms-num-reviews-bottom' ).show();
-
- } else {
- $( '.llms-num-reviews-bottom' ).hide();
- }
- $( '#_llms_display_reviews' ).change(function() {
- if ( $( '#_llms_display_reviews' ).attr( 'checked' ) ) {
- $( '.llms-num-reviews-top' ).addClass( 'top' );
- $( '.llms-num-reviews-bottom' ).show();
- } else {
- $( '.llms-num-reviews-top' ).removeClass( 'top' );
- $( '.llms-num-reviews-bottom' ).hide();
- }
- });
-
- },
- };
-
- /* global LLMS, $ */
-
- /*!
- * JavaScript Cookie v2.2.1
- * https://github.com/js-cookie/js-cookie
- *
- * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
- * Released under the MIT license
- */
- ;(function (factory) {
- var registeredInModuleLoader;
- if (typeof define === 'function' && define.amd) {
- define(factory);
- registeredInModuleLoader = true;
- }
- if (typeof exports === 'object') {
- module.exports = factory();
- registeredInModuleLoader = true;
- }
- if (!registeredInModuleLoader) {
- var OldCookies = window.Cookies;
- var api = window.Cookies = factory();
- api.noConflict = function () {
- window.Cookies = OldCookies;
- return api;
- };
- }
- }(function () {
- function extend () {
- var i = 0;
- var result = {};
- for (; i < arguments.length; i++) {
- var attributes = arguments[ i ];
- for (var key in attributes) {
- result[key] = attributes[key];
- }
- }
- return result;
- }
-
- function decode (s) {
- return s.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent);
- }
-
- function init (converter) {
- function api() {}
-
- function set (key, value, attributes) {
- if (typeof document === 'undefined') {
- return;
- }
-
- attributes = extend({
- path: '/'
- }, api.defaults, attributes);
-
- if (typeof attributes.expires === 'number') {
- attributes.expires = new Date(new Date() * 1 + attributes.expires * 864e+5);
- }
-
- // We're using "expires" because "max-age" is not supported by IE
- attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
-
- try {
- var result = JSON.stringify(value);
- if (/^[\{\[]/.test(result)) {
- value = result;
- }
- } catch (e) {}
-
- value = converter.write ?
- converter.write(value, key) :
- encodeURIComponent(String(value))
- .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
-
- key = encodeURIComponent(String(key))
- .replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent)
- .replace(/[\(\)]/g, escape);
-
- var stringifiedAttributes = '';
- for (var attributeName in attributes) {
- if (!attributes[attributeName]) {
- continue;
- }
- stringifiedAttributes += '; ' + attributeName;
- if (attributes[attributeName] === true) {
- continue;
- }
-
- // Considers RFC 6265 section 5.2:
- // ...
- // 3. If the remaining unparsed-attributes contains a %x3B (";")
- // character:
- // Consume the characters of the unparsed-attributes up to,
- // not including, the first %x3B (";") character.
- // ...
- stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];
- }
-
- return (document.cookie = key + '=' + value + stringifiedAttributes);
- }
-
- function get (key, json) {
- if (typeof document === 'undefined') {
- return;
- }
-
- var jar = {};
- // To prevent the for loop in the first place assign an empty array
- // in case there are no cookies at all.
- var cookies = document.cookie ? document.cookie.split('; ') : [];
- var i = 0;
-
- for (; i < cookies.length; i++) {
- var parts = cookies[i].split('=');
- var cookie = parts.slice(1).join('=');
-
- if (!json && cookie.charAt(0) === '"') {
- cookie = cookie.slice(1, -1);
- }
-
- try {
- var name = decode(parts[0]);
- cookie = (converter.read || converter)(cookie, name) ||
- decode(cookie);
-
- if (json) {
- try {
- cookie = JSON.parse(cookie);
- } catch (e) {}
- }
-
- jar[name] = cookie;
-
- if (key === name) {
- break;
- }
- } catch (e) {}
- }
-
- return key ? jar[key] : jar;
- }
-
- api.set = set;
- api.get = function (key) {
- return get(key, false /* read as raw */);
- };
- api.getJSON = function (key) {
- return get(key, true /* read as json */);
- };
- api.remove = function (key, attributes) {
- set(key, '', extend(attributes, {
- expires: -1
- }));
- };
-
- api.defaults = {};
-
- api.withConverter = init;
-
- return api;
- }
-
- return init(function () {});
- }));
-
- /**
- * Create a no conflict reference to JS Cookies.
- *
- * @type {Object}
- */
- LLMS.CookieStore = Cookies.noConflict();
-
- /**
- * Store information in Local Storage by group.
- *
- * @since 3.36.0
- * @since 3.37.14 Use persistent reference to JS Cookies.
- * @since 4.2.0 Set sameSite to `strict` for cookies.
- *
- * @param string group Storage group id/name.
- */
- LLMS.Storage = function( group ) {
-
- var self = this,
- store = LLMS.CookieStore;
-
- /**
- * Clear all data for the group.
- *
- * @since 3.36.0
- *
- * @return void
- */
- this.clearAll = function() {
- store.remove( group );
- };
-
- /**
- * Clear a single item from the group by key.
- *
- * @since 3.36.0
- *
- * @return obj
- */
- this.clear = function( key ) {
- var data = self.getAll();
- delete data[ key ];
- return store.set( group, data );
- };
-
- /**
- * Retrieve (and parse) all data stored for the group.
- *
- * @since 3.36.0
- *
- * @return obj
- */
- this.getAll = function() {
- return store.getJSON( group ) || {};
- }
-
- /**
- * Retrieve an item from the group by key.
- *
- * @since 3.36.0
- *
- * @param string key Item key/name.
- * @param mixed default_val Item default value to be returned when item not found in the group.
- * @return mixed
- */
- this.get = function( key, default_val ) {
- var data = self.getAll();
- return data[ key ] ? data[ key ] : default_val;
- }
-
- /**
- * Store an item in the group by key.
- *
- * @since 3.36.0
- * @since 4.2.0 Set sameSite to `strict` for cookies.
- *
- * @param string key Item key name.
- * @param mixed val Item value
- * @return obj
- */
- this.set = function( key, val ) {
- var data = self.getAll();
- data[ key ] = val;
- return store.set( group, data, { sameSite: 'strict' } );
- };
-
- }
-
- /**
- * Student Dashboard related JS
- *
- * @package LifterLMS/Scripts
- *
- * @since 3.7.0
- * @since 3.10.0 Bind events on the orders screen.
- * @since 5.0.0 Removed redundant password toggle logic for edit account screen.
- * @version 5.0.0
- */
- LLMS.StudentDashboard = {
-
- /**
- * Slug for the current screen/endpoint
- *
- * @type {String}
- */
- screen: '',
-
- /**
- * Init
- *
- * @since 3.7.0
- * @since 3.10.0 Unknown
- * @since 5.0.0 Removed password toggle logic.
- *
- * @return void
- */
- init: function() {
-
- if ( $( '.llms-student-dashboard' ).length ) {
- this.bind();
- if ( 'orders' === this.get_screen() ) {
- this.bind_orders();
- }
- }
-
- },
-
- /**
- * Bind DOM events
- *
- * @since 3.7.0
- * @since 3.7.4 Unknown.
- * @since 5.0.0 Removed password toggle logic.
- *
- * @return void
- */
- bind: function() {
-
- $( '.llms-donut' ).each( function() {
- LLMS.Donut( $( this ) );
- } );
-
- },
-
- /**
- * Bind events related to the orders screen on the dashboard
- *
- * @since 3.10.0
- *
- * @return void
- */
- bind_orders: function() {
-
- $( '#llms-cancel-subscription-form' ).on( 'submit', this.order_cancel_warning );
- $( '#llms_update_payment_method' ).on( 'click', function() {
- $( 'input[name="llms_payment_gateway"]:checked' ).trigger( 'change' );
- $( this ).closest( 'form' ).find( '.llms-switch-payment-source-main' ).slideToggle( '200' );
- } );
-
- },
-
- /**
- * Get the current dashboard endpoint/tab slug
- *
- * @since 3.10.0
- *
- * @return void
- */
- get_screen: function() {
- if ( ! this.screen ) {
- this.screen = $( '.llms-student-dashboard' ).attr( 'data-current' );
- }
- return this.screen;
- },
-
- /**
- * Show a confirmation warning when Cancel Subscription form is submitted
- *
- * @since 3.10.0
- *
- * @param obj e JS event data.
- * @return void
- */
- order_cancel_warning: function( e ) {
- e.preventDefault();
- var msg = LLMS.l10n.translate( 'Are you sure you want to cancel your subscription?' );
- if ( window.confirm( LLMS.l10n.translate( msg ) ) ) {
- $( this ).off( 'submit', this.order_cancel_warning );
- $( this ).submit();
- }
- },
-
- };
-
- /* global LLMS, $ */
-
- /**
- * User event/interaction tracking.
- *
- * @since 3.36.0
- * @since 3.36.2 Fix JS error when settings aren't loaded.
- * @since 3.37.2 When adding an event to the storae also make sure the nonce is set for server-side verification.
- * @since 3.37.9 Fix IE compatibility issue related to usage of `Object.assign()`.
- * @since 3.37.14 Persist the tracking events via ajax when reaching the cookie size limit.
- * @since 5.0.0 Set `settings` as an empty object when no settings supplied.
- * @since 7.1.0 Only attempt to add a nonce to the datastore when a nonce exists in the settings object.
- */
- LLMS.Tracking = function( settings ) {
-
- settings = settings || {};
-
- var self = this,
- store = new LLMS.Storage( 'llms-tracking' );
-
- settings = 'string' === typeof settings ? JSON.parse( settings ) : settings;
-
- /**
- * Initialize / Bind all tracking event listeners.
- *
- * @since 3.36.0
- * @since 5.0.0 Only attempt to add a nonce to the datastore when a nonce exists in the settings object.
- * @since 7.1.0 Do not add a nonce to the datastore by default, will be added/updated
- * when storing an event to track.
- *
- * @return {void}
- */
- function init() {
-
- self.addEvent( 'page.load' );
-
- window.addEventListener( 'beforeunload', onBeforeUnload );
- window.addEventListener( 'unload', onUnload );
-
- document.addEventListener( 'visibilitychange', onVisibilityChange );
-
- };
-
- /**
- * Add an event.
- *
- * @since 3.36.0
- * @since 3.36.2 Fix error when settings aren't loaded.
- * @since 3.37.2 Always make sure the nonce is set for server-side verification.
- * @since 3.37.14 Persist the tracking events via ajax when reaching the cookie size limit.
- * @since 7.1.0 Only attempt to add a nonce to the datastore when a nonce exists in the settings object.
- *
- * @param string|obj event Event Id (type.event) or a full event object from `this.makeEventObj()`.
- * @param int args Optional additional arguments to pass to `this.makeEventObj()`.
- * @return {void}
- */
- this.addEvent = function( event, args ) {
-
- args = args || {};
- if ( 'string' === typeof event ) {
- args.event = event;
- }
-
- // If the event isn't registered in the settings don't proceed.
- if ( !settings.events || -1 === settings.events.indexOf( args.event ) ) {
- return;
- }
-
- // Make sure the nonce is set for server-side verification.
- if ( settings.nonce ) {
- store.set( 'nonce', settings.nonce );
- }
-
- event = self.makeEventObj( args );
-
- var all = store.get( 'events', [] );
- all.push( event );
- store.set( 'events', all );
-
- // If couldn't store the latest event because of size limits.
- if ( all.length > store.get( 'events', [] ).length ) {
-
- // Copy the cookie in a temporary variable.
- var _temp = store.getAll();
- // Clear the events from the cookie.
- store.clear('events');
-
- // Add the latest event to the temporary variable.
- _temp['events'].push( event );
-
- // Send the temporary variable as string via ajax.
- LLMS.Ajax.call( {
- data: {
- action: 'persist_tracking_events',
- 'llms-tracking': JSON.stringify(_temp)
- },
-
- error: function( xhr, status, error ) {
-
- console.log( xhr, status, error );
-
- },
- success: function( r ) {
-
- if ( 'error' === r.code ) {
- console.log(r.code, r.message);
- }
-
- }
-
- } );
-
- }
-
- }
-
- /**
- * Retrieve initialization settings.
- *
- * @since 3.36.0
- *
- * @return obj
- */
- this.getSettings = function() {
- return settings;
- }
-
- /**
- * Create an event object suitable to save as an event.
- *
- * @since 3.36.0
- * @since 3.37.9 Use `$.extend()` in favor of `Object.assign()`.
- *
- * @param obj event {
- * Event hash
- *
- * @param {string} event (Required) Event ID, eg: "page.load".
- * @param {url} url Event URL. (Optional, added automatically) Stored as metadata and used to infer an object_id for post events.
- * @param {time} float (Optional, added automatically) Timestamp (in milliseconds). Used for the event creation date.
- * @param {int} obj_id (Optional). The object ID. Inferred automatically via `url` if not provided.
- * @param {obj} meta (Optional) Hash of metadata to store with the event.
- * }
- * @return obj
- */
- this.makeEventObj = function( event ) {
- return $.extend( event, {
- url: window.location.href,
- time: Math.round( new Date().getTime() / 1000 ),
- } );
- }
-
-
- /**
- * Remove the visibility change event listener on window.beforeunload
- *
- * Prevents actual unloading from recording a blur event from the visibility change listener
- *
- * @param obj e JS event object.
- * @return void
- */
- function onBeforeUnload( e ) {
- document.removeEventListener( 'visibilitychange', onVisibilityChange );
- }
-
- /**
- * Record a `page.exit` event on window.unload.
- *
- * @since 3.36.0
- *
- * @param obj e JS event object.
- * @return void
- */
- function onUnload( e ) {
- self.addEvent( 'page.exit' );
- }
-
- /**
- * Record `page.blur` and `page.focus` events via document.visilibitychange events.
- *
- * @since 3.36.0
- *
- * @param obj e JS event object.
- * @return void
- */
- function onVisibilityChange( e ) {
-
- var event = document.hidden ? 'page.blur' : 'page.focus';
- self.addEvent( event );
-
- }
-
- // Initialize on the frontend only.
- if ( ! $( 'body' ).hasClass( 'wp-admin' ) ) {
- init();
- }
-
- };
-
- llms.tracking = new LLMS.Tracking( llms.tracking );
-
- /**
- * Rest Methods
- * Manages URL and Rest object parsing
- *
- * @package LifterLMS/Scripts
- *
- * @since Unknown
- * @version Unknown
- */
-
- LLMS.Rest = {
-
- /**
- * Init
- * loads class methods
- */
- init: function() {
- this.bind();
- },
-
- /**
- * Bind Method
- * Handles dom binding on load
- *
- * @return {[type]} [description]
- */
- bind: function() {
- },
-
- /**
- * Searches for string matches in url path
- *
- * @param {Array} strings [Array of strings to search for matches]
- * @return {Boolean} [Was a match found?]
- */
- is_path: function( strings ) {
-
- var path_exists = false,
- url = window.location.href;
-
- for ( var i = 0; i < strings.length; i++ ) {
-
- if ( url.search( strings[i] ) > 0 && ! path_exists ) {
-
- path_exists = true;
- }
- }
-
- return path_exists;
- },
-
- /**
- * Retrieves query variables
- *
- * @return {[Array]} [array object of query variable key=>value pairs]
- */
- get_query_vars: function() {
-
- var vars = [], hash,
- hashes = window.location.href.slice( window.location.href.indexOf( '?' ) + 1 ).split( '&' );
-
- for (var i = 0; i < hashes.length; i++) {
- hash = hashes[i].split( '=' );
- vars.push( hash[0] );
- vars[hash[0]] = hash[1];
- }
-
- return vars;
- }
-
- };
-
-
- (()=>{"use strict";var t={d:(n,e)=>{for(var r in e)t.o(e,r)&&!t.o(n,r)&&Object.defineProperty(n,r,{enumerable:!0,get:e[r]})},o:(t,n)=>Object.prototype.hasOwnProperty.call(t,n),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},n={};t.r(n),t.d(n,{get:()=>d,start:()=>p,stop:()=>c});const e="llms-spinning",r="default",o=window.wp.i18n;function i(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:r;const i=document.createElement("div"),l=(0,o.__)("Loading…","lifterlms");return i.innerHTML=`${l}`,i.classList.add(e),t.appendChild(i),i}function l(t){if((t="string"==typeof t?document.querySelectorAll(t):t)instanceof NodeList)return Array.from(t);const n=[];return t instanceof Element?n.push(t):"undefined"!=typeof jQuery&&t instanceof jQuery&&t.toArray().forEach((t=>n.push(t))),n}function s(t){const n=t.querySelectorAll(".llms-spinning");return n.length?Array.from(n).find((n=>t===n.parentNode)):null}function a(){const t="llms-spinner-styles";if(!document.getElementById(t)){const n=document.createElement("style");n.textContent="\n\t.llms-spinning {\n\t\tbackground: rgba( 250, 250, 250, 0.7 );\n\t\tbottom: 0;\n\t\tdisplay: none;\n\t\tleft: 0;\n\t\tposition: absolute;\n\t\tright: 0;\n\t\ttop: 0;\n\t\tz-index: 2;\n\t}\n\n\t.llms-spinner {\n\t\tanimation: llms-spinning 1.5s linear infinite;\n\t\tbox-sizing: border-box;\n\t\tborder: 4px solid #313131;\n\t\tborder-radius: 50%;\n\t\theight: 40px;\n\t\tleft: 50%;\n\t\tmargin-left: -20px;\n\t\tmargin-top: -20px;\n\t\tposition: absolute;\n\t\ttop: 50%;\n\t\twidth: 40px;\n\n\t}\n\n\t.llms-spinner.small {\n\t\tborder-width: 2px;\n\t\theight: 20px;\n\t\tmargin-left: -10px;\n\t\tmargin-top: -10px;\n\t\twidth: 20px;\n\t}\n\n\t@keyframes llms-spinning {\n\t\t0% {\n\t\t\ttransform: rotate( 0deg )\n\t\t}\n\t\t50% {\n\t\t\tborder-radius: 5%;\n\t\t}\n\t\t100% {\n\t\t\ttransform: rotate( 220deg) \n\t\t}\n\t}\n".replace(/\n/g,"").replace(/\t/g," ").replace(/\s\s+/g," "),n.id=t,document.head.appendChild(n)}}function d(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:r,e=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];a();const o=l(t);if(!o.length)return null;const d=o[0],p=s(d)||i(d,n);return e&&"undefined"!=typeof jQuery?jQuery(p):p}function p(t){let n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:r;l(t).forEach((t=>{const e=d(t,n,!1);e&&(e.style.display="block")}))}function c(t){l(t).forEach((t=>{const n=d(t,r,!1);n&&(n.style.display="none")}))}window.LLMS=window.LLMS||{},window.LLMS.Spinner=n})();
-
- /**
- * Initializes all classes within the LLMS Namespace
- *
- * @since Unknown
- *
- * @return {void}
- */
- LLMS.init = function() {
-
- for (var func in LLMS) {
-
- if ( typeof LLMS[func] === 'object' && LLMS[func] !== null ) {
-
- if ( LLMS[func].init !== undefined ) {
-
- if ( typeof LLMS[func].init === 'function') {
- LLMS[func].init();
- }
-
- }
-
- }
-
- }
-
- };
-
- /**
- * Determine if the current device is touch-enabled
- *
- * @since 3.24.3
- *
- * @see {@link https://stackoverflow.com/a/4819886/400568}
- *
- * @return {Boolean} Whether or not the device is touch-enabled.
- */
- LLMS.is_touch_device = function() {
-
- var prefixes = ' -webkit- -moz- -o- -ms- '.split( ' ' );
- var mq = function( query ) {
- return window.matchMedia( query ).matches;
- }
-
- if ( ( 'ontouchstart' in window ) || window.DocumentTouch && document instanceof DocumentTouch ) {
- return true;
- }
-
- /**
- * Include the 'heartz' as a way to have a non matching MQ to help terminate the join.
- *
- * @see {@link https://git.io/vznFH}
- */
- var query = ['(', prefixes.join( 'touch-enabled),(' ), 'heartz', ')'].join( '' );
- return mq( query );
-
- };
-
- /**
- * Wait for matchHeight to load
- *
- * @since 3.0.0
- * @since 3.16.6 Unknown.
- * @since 5.3.3 Pass a dependency name to `wait_for()`.
- *
- * @param {Function} cb Callback function to run when matchheight is ready.
- * @return {void}
- */
- LLMS.wait_for_matchHeight = function( cb ) {
- this.wait_for( function() {
- return ( undefined !== $.fn.matchHeight );
- }, cb, 'matchHeight' );
- }
-
- /**
- * Wait for webuiPopover to load
- *
- * @since 3.9.1
- * @since 3.16.6 Unknown.
- *
- * @param {Function} cb Callback function to run when matchheight is ready.
- * @return {void}
- */
- LLMS.wait_for_popover = function( cb ) {
- this.wait_for( function() {
- return ( undefined !== $.fn.webuiPopover );
- }, cb, 'webuiPopover' );
- }
-
- /**
- * Wait for a dependency to load and then run a callback once it has
- *
- * Temporary fix for a less-than-optimal assets loading function on the PHP side of things.
- *
- * @since 3.9.1
- * @since 5.3.3 Added optional `name` parameter.
- *
- * @param {Function} test A function that returns a truthy if the dependency is loaded.
- * @param {Function} cb A callback function executed once the dependency is loaded.
- * @param {string} name The dependency name.
- * @return {void}
- */
- LLMS.wait_for = function( test, cb, name ) {
-
- var counter = 0,
- interval;
-
- name = name ? name : 'unnamed';
-
- interval = setInterval( function() {
-
- // If we get to 30 seconds log an error message.
- if ( counter >= 300 ) {
-
- console.log( 'Unable to load dependency: ' + name );
-
- // If we can't access yet, increment and wait...
- } else {
-
- // Bind the events, we're good!
- if ( test() ) {
- cb();
- } else {
- // console.log( 'Waiting for dependency: ' + name );
- counter++;
- return;
- }
-
- }
-
- clearInterval( interval );
-
- }, 100 );
-
- };
-
- LLMS.init( $ );
-
-} )( jQuery );
-
-//# sourceMappingURL=../maps/js/llms.js.map
diff --git a/assets/js/llms.min.js b/assets/js/llms.min.js
deleted file mode 100644
index e87887cf16..0000000000
--- a/assets/js/llms.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-var LLMS=window.LLMS||{};!function(l){"use strict";var t,e,n;LLMS.Achievements={init:function(){var t;l(".llms-achievement").length&&(t=this,l(function(){t.bind(),t.maybe_open()}))},bind:function(){var n=this;l(".llms-achievement").each(function(){n.create_modal(l(this))}),l(".llms-achievement").on("click",function(){var t=l(this),e="achievement-"+t.attr("data-id"),e=l("#"+e);e.length||n.create_modal(t),e.iziModal("open")})},create_modal:function(e){var t="achievement-"+e.attr("data-id"),n=l("#"+t);n.length||(n=l(''),l("body").append(n)),n.iziModal({headerColor:"#3a3a3a",group:"achievements",history:!0,loop:!0,overlayColor:"rgba( 0, 0, 0, 0.6 )",transitionIn:"fadeInDown",transitionOut:"fadeOutDown",width:340,onOpening:function(t){t.setTitle(e.find(".llms-achievement-title").html()),t.setSubtitle(e.find(".llms-achievement-date").html()),t.setContent(''+e.html()+"
")},onClosing:function(){window.history.pushState("",document.title,window.location.pathname+window.location.search)}})},maybe_open:function(){var t=window.location.hash.split("-");2===t.length&&(t[1]=parseInt(t[1]),"#achievement-"===t[0]&&Number.isInteger(t[1])&&(t=document.querySelector(`a[href="${t.join("-")}"]`))&&t.click())}},LLMS.Ajax={url:window.ajaxurl||window.llms.ajaxurl,type:"post",data:[],cache:!1,dataType:"json",async:!0,response:[],init:function(t){if(null===t||"object"!=typeof t)return!1;t.url=("url"in t?t:this).url,t.type=("type"in t?t:this).type,t.data=("data"in t?t:this).data,t.cache=("cache"in t?t:this).cache,t.dataType=("dataType"in t?t:this).dataType,t.async=("async"in t?t:this).async,t.data._ajax_nonce=window.llms.ajax_nonce||wp_ajax_data.nonce;var e=LLMS.Rest.get_query_vars();return t.data.post_id="post"in e?e.post:null,!t.data.post_id&&l("input#post_ID").length&&(t.data.post_id=l("input#post_ID").val()),t},call:function(t){t=this.init(t);return!!t&&(this.request(t),this)},request:function(t){return l.ajax(t),this}},LLMS.Donut=function(t){function e(t){this.settings=l.extend({element:t.element,percent:100},t),this.circle=this.settings.element.find("path"),this.settings.stroke_width=parseInt(this.circle.css("stroke-width")),this.radius=(parseInt(this.settings.element.css("width"))-this.settings.stroke_width)/2,this.angle=l("body").hasClass("rtl")?82.5:97.5,this.i=Math.round(.75*this.settings.percent),this.first=!0,this.increment=l("body").hasClass("rtl")?-5:5,this.animate=function(){this.timer=setInterval(this.loop.bind(this),10)},this.loop=function(){this.angle+=this.increment,this.angle%=360;var t,e=this.angle/180*Math.PI,n=this.radius+this.settings.stroke_width/2+Math.cos(e)*this.radius,e=this.radius+this.settings.stroke_width/2+Math.sin(e)*this.radius;!0===this.first?(t=this.circle.attr("d")+" M "+n+" "+e,this.first=!1):t=this.circle.attr("d")+" L "+n+" "+e,this.circle.attr("d",t),this.i--,this.i<=0&&clearInterval(this.timer)}}(t=t).append(''),new e({element:t,percent:t.attr("data-perc")}).animate()},LLMS.Forms={address_info:{},$cities:null,$countries:null,$states:null,$states_holder:null,init:function(){var t;l("body").hasClass("wp-admin")&&!l("body").hasClass("profile-php")&&!l("body").hasClass("user-edit-php")||((t=this).bind_matching_fields(),t.bind_voucher_field(),t.bind_edit_account(),t.bind_l10n_selects())},bind_edit_account:function(){l("form.llms-person-form.edit-account").length&&l(".llms-toggle-fields").on("click",this.handle_toggle_click)},bind_l10n_selects:function(){var e=this;e.$cities=l("#llms_billing_city"),e.$countries=l(".llms-l10n-country-select select"),e.$states=l(".llms-l10n-state-select select"),e.$zips=l("#llms_billing_zip"),e.$countries.length&&LLMS.wait_for(function(){return void 0!==l.fn.llmsSelect2},function(){e.$states.length&&e.prep_state_field(),e.$countries.add(e.$states).llmsSelect2({width:"100%"}),window.llms.address_info&&(e.address_info=JSON.parse(window.llms.address_info)),e.$countries.on("change",function(){var t=l(this).val();e.update_locale_info(t)}).trigger("change")},"llmsSelect2")},bind_matching_fields:function(){l("input[data-match]").not('[type="password"]').each(function(){var n,i=l(this),s=l("#"+i.attr("data-match"));s.length&&(n=i.closest(".llms-form-field").add(s.closest(".llms-form-field")),i.on("input change",function(){var t=i.val(),e=s.val();t&&e&&t!==e?n.addClass("invalid"):n.removeClass("invalid")}))})},bind_voucher_field:function(){l("#llms-voucher-toggle").on("click",function(t){t.preventDefault(),l("#llms_voucher").toggle()})},get_field_parent:function(t){return t.closest(".llms-form-field")},get_label_text:function(t){t=t.clone();return t.find("*").remove(),t.text().trim()},handle_toggle_click:function(t){t.preventDefault();var t=l(this),e=l(l(this).attr("data-fields")),n=t.attr("data-is-showing")||"no",i="yes"===n?"hide":"show",s="yes"===n?"disabled":null,o="yes"===n?"data-change-text":"data-cancel-text";e.each(function(){l(this).closest(".llms-form-field")[i](),l(this).attr("disabled",s)}),t.text(t.attr(o)),t.attr("data-is-showing","yes"===n?"no":"yes")},prep_state_field:function(){var t=this.$states.closest(".llms-form-field");this.$holder=l(''),this.$holder.appendTo(t),this.$states.find("optgroup").appendTo(this.$holder)},update_label:function(t,e){var t=this.get_field_parent(t).find("label"),n=t.find(".llms-required").clone();t.html(e),t.append(n)},update_locale_info:function(t){var e;this.address_info&&this.address_info[t]&&(e=this.address_info[t],this.update_state_options(t),this.update_label(this.$states,e.state),this.update_locale_info_for_field(this.$cities,e.city),this.update_locale_info_for_field(this.$zips,e.postcode))},update_locale_info_for_field:function(t,e){e?(this.update_label(t,e),this.enable_field(t)):this.disable_field(t)},update_state_options:function(t){this.$states.length&&((t=this.$holder.find('optgroup[data-key="'+t+'"] option').clone()).length?(this.enable_field(this.$states),this.$states.html(t)):(this.$states.html(""),this.disable_field(this.$states)))},disable_field:function(t){l("",{name:t.attr("name"),class:t.attr("class")+" hidden",type:"hidden"}).insertAfter(t),t.attr("disabled","disabled"),this.get_field_parent(t).hide()},enable_field:function(t){t.removeAttr("disabled"),t.next(".hidden[name="+t.attr("name")+"]").detach(),this.get_field_parent(t).show()}},LLMS.Instructors={init:function(){var t=this;l("body").hasClass("wp-admin")||l(".llms-instructors").length&&LLMS.wait_for_matchHeight(function(){t.bind()})},bind:function(){l(".llms-instructors .llms-author").matchHeight()}},LLMS.l10n=LLMS.l10n||{},LLMS.l10n.translate=function(t){return this.strings[t]||t},LLMS.l10n.replace=function(t,e){var n=this.translate(t);return l.each(e,function(t,e){-1!==t.indexOf("s")?e=e.toString():-1!==t.indexOf("d")&&(e=+e),n=n.replace(t,e)}),n},LLMS.LessonPreview={$els:null,init:function(){var t=this;this.$locked=l('a[href="#llms-lesson-locked"]'),this.$locked.length&&t.bind(),l(".llms-course-navigation").length&&LLMS.wait_for_matchHeight(function(){t.match_height()})},bind:function(){var n=this;this.$locked.on("click",function(){return!1}),this.$locked.on("mouseenter",function(){var t,e=l(this).find(".llms-tooltip");e.length||(t=(t=l(this).attr("data-tooltip-msg"))||LLMS.l10n.translate("You do not have permission to access this content"),e=n.get_tooltip(t),l(this).append(e)),setTimeout(function(){e.addClass("show")},10)}),this.$locked.on("mouseleave",function(){l(this).find(".llms-tooltip").removeClass("show")})},match_height:function(){l(".llms-course-navigation .llms-lesson-link").matchHeight()},get_tooltip:function(t){var e=l('');return e.append(''+t+"
"),e}},LLMS.Loops={init:function(){var t=this;l(".llms-loop").length&&LLMS.wait_for_matchHeight(function(){t.match_height()})},match_height:function(){l(".llms-loop-item .llms-loop-item-content").matchHeight(),l(".llms-achievement-loop-item .llms-achievement").matchHeight(),l(".llms-certificate-loop-item .llms-certificate").matchHeight()}},LLMS.OutlineCollapse={$outlines:null,init:function(){this.$outlines=l(".llms-widget-syllabus--collapsible"),this.$outlines.length&&this.bind()},bind:function(){var i=this;this.$outlines.each(function(){var t=l(this),e=t.find(".llms-section .section-header");e.on("click",function(t){t.preventDefault();var e=l(this).closest(".llms-section");switch(i.get_section_state(e)){case"closed":i.open_section(e);break;case"opened":i.close_section(e)}}),t.find(".llms-collapse-toggle").on("click",function(t){t.preventDefault();var n="close"===l(this).attr("data-action")?"opened":"closed";e.each(function(){var t=l(this).closest(".llms-section"),e=i.get_section_state(t);if(n!==e)return!0;switch(e){case"closed":i.close_section(t);break;case"opened":i.open_section(t)}l(this).trigger("click")})})})},close_section:function(t){t.removeClass("llms-section--opened").addClass("llms-section--closed")},open_section:function(t){t.removeClass("llms-section--closed").addClass("llms-section--opened")},get_section_state:function(t){return t.hasClass("llms-section--opened")?"opened":"closed"}},l.extend(LLMS.PasswordStrength,{$meter:l(".llms-password-strength-meter"),$pass:null,$conf:null,$form:null,init:function(){var t;l("body").hasClass("wp-admin")||this.setup_references()&&(t=this,LLMS.wait_for(function(){return"undefined"!=typeof wp&&void 0!==wp.passwordStrength},function(){t.bind(),t.$form.trigger("llms-password-strength-ready")}))},bind:function(){var t=this;this.$form.hasClass("llms-checkout")||t.$form.on("submit",t,t.submit),t.$pass.add(t.$conf).on("keyup",function(){t.check_strength()})},check_strength:function(){var t=this.$pass.closest(".llms-form-field"),e=this.$conf&&this.$conf.length?this.$conf.closest(".llms-form-field"):null,n=this.$pass.val().length,i=this.$conf&&this.$conf.length?this.$conf.val().length:0;n||i?(this.get_current_strength_status()?(t.removeClass("invalid").addClass("valid"),i&&e.removeClass("invalid").addClass("valid")):(t.removeClass("valid").addClass("invalid"),i&&e.removeClass("valid").addClass("invalid")),this.$meter.removeClass("too-short very-weak weak medium strong mismatch"),this.$meter.show().addClass(this.get_current_strength("slug")),this.$meter.html(this.get_current_strength("text"))):(t.removeClass("valid invalid"),e&&e.removeClass("valid invalid"),this.$meter.hide())},checkout:function(t,e){t.get_current_strength_status()?e(!0):e(LLMS.l10n.translate("There is an issue with your chosen password."))},get_blocklist:function(){var e=wp.passwordStrength.userInputDisallowedList().concat(this.get_setting("blocklist",[]));return this.$form.find('input[type="text"], input[type="email"], input[type="tel"], input[type="number"]').each(function(){var t=l(this).val();t&&e.push(t)}),e},get_current_strength:function(t){t=t||"int";var e,n=this.$pass.val(),i=this.$conf&&this.$conf.length?this.$conf.val():"";return n.length');return e.append(t.$element.closest(".llms-access-plan").find(".llms-access-plan-restrictions ul").clone()),e},placement:"top",style:"inverse",title:LLMS.l10n.translate("Members Only Pricing"),width:"280px"})})}},LLMS.Quiz_Attempt={init:function(){l(".llms-quiz-attempt-question-header a.toggle-answer").on("click",function(t){t.preventDefault();t=l(this).closest("header").next(".llms-quiz-attempt-question-main");l(this).closest("li").siblings().find(".llms-quiz-attempt-question-main").slideUp(200),t.is(":visible")?t.slideUp(200):t.slideDown(200)})}},LLMS.Review={init:function(){this.bind()},bind:function(){l("#llms_review_submit_button").click(function(){""!==l("#review_title").val()&&""!==l("#review_text").val()?jQuery.ajax({type:"post",dataType:"json",url:window.llms.ajaxurl,data:{action:"LLMSSubmitReview",review_title:l("#review_title").val(),review_text:l("#review_text").val(),pageID:l("#post_ID").val(),llms_review_nonce:l("#llms_review_nonce").val()},success:function(){console.log("Review success"),l("#review_box").hide("swing"),l("#thank_you_box").show("swing")},error:function(t,e,n){console.log(t),console.log(e),console.log(n)}}):(""===l("#review_title").val()?l("#review_title_error").show("swing"):l("#review_title_error").hide("swing"),""===l("#review_text").val()?l("#review_text_error").show("swing"):l("#review_text_error").hide("swing"))}),l("#_llms_display_reviews").attr("checked")?(l(".llms-num-reviews-top").addClass("top"),l(".llms-num-reviews-bottom").show()):l(".llms-num-reviews-bottom").hide(),l("#_llms_display_reviews").change(function(){l("#_llms_display_reviews").attr("checked")?(l(".llms-num-reviews-top").addClass("top"),l(".llms-num-reviews-bottom").show()):(l(".llms-num-reviews-top").removeClass("top"),l(".llms-num-reviews-bottom").hide())})}},t=function(){function a(){for(var t=0,e={};ts.get("events",[]).length&&(e=s.getAll(),s.clear("events"),e.events.push(t),LLMS.Ajax.call({data:{action:"persist_tracking_events","llms-tracking":JSON.stringify(e)},error:function(t,e,n){console.log(t,e,n)},success:function(t){"error"===t.code&&console.log(t.code,t.message)}})))},this.getSettings=function(){return n},this.makeEventObj=function(t){return l.extend(t,{url:window.location.href,time:Math.round((new Date).getTime()/1e3)})},l("body").hasClass("wp-admin")||(i.addEvent("page.load"),window.addEventListener("beforeunload",t),window.addEventListener("unload",e),document.addEventListener("visibilitychange",o))},llms.tracking=new LLMS.Tracking(llms.tracking),LLMS.Rest={init:function(){this.bind()},bind:function(){},is_path:function(t){for(var e=!1,n=window.location.href,i=0;i{for(var n in e)i.o(e,n)&&!i.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},s={};i.r(s),i.d(s,{get:()=>o,start:()=>function(t){let e=1{t=o(t,e,!1);t&&(t.style.display="block")})},stop:()=>function(t){a(t).forEach(t=>{t=o(t,c,!1);t&&(t.style.display="none")})}});const r="llms-spinning",c="default",d=window.wp.i18n;function a(t){if((t="string"==typeof t?document.querySelectorAll(t):t)instanceof NodeList)return Array.from(t);const e=[];return t instanceof Element?e.push(t):"undefined"!=typeof jQuery&&t instanceof jQuery&&t.toArray().forEach(t=>e.push(t)),e}function o(t){var e,n,i=1n===t.parentNode):null)||function(t,e){var e=1${i}`,n.classList.add(r),t.appendChild(n),n}(e,i),s&&"undefined"!=typeof jQuery?jQuery(o):o):null}window.LLMS=window.LLMS||{},window.LLMS.Spinner=s}LLMS.init=function(){for(var t in LLMS)"object"==typeof LLMS[t]&&null!==LLMS[t]&&void 0!==LLMS[t].init&&"function"==typeof LLMS[t].init&&LLMS[t].init()},LLMS.is_touch_device=function(){var t=" -webkit- -moz- -o- -ms- ".split(" ");return!!("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)||(t=["(",t.join("touch-enabled),("),"heartz",")"].join(""),window.matchMedia(t).matches)},LLMS.wait_for_matchHeight=function(t){this.wait_for(function(){return void 0!==l.fn.matchHeight},t,"matchHeight")},LLMS.wait_for_popover=function(t){this.wait_for(function(){return void 0!==l.fn.webuiPopover},t,"webuiPopover")},LLMS.wait_for=function(t,e,n){var i,s=0;n=n||"unnamed",i=setInterval(function(){if(300<=s)console.log("Unable to load dependency: "+n);else{if(!t())return void s++;e()}clearInterval(i)},100)},LLMS.init(l)}(jQuery);
-//# sourceMappingURL=../maps/js/llms.min.js.map