PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.9
4.4.9 4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 All 140 releases
← All changes | assets/dist/js/admin/admin-courses.js +230 -93 4.3.9 → 4.4.9 View file →
@@ -1,4 +1,4 @@
1 1 /******/ (() => { // webpackBootstrap
2 2 /******/ var __webpack_modules__ = ({
3 3
4 4 /***/ "./assets/src/js/admin/courses/generate-with-ai.js"
@@ -15,10 +15,10 @@
15 15 /* harmony import */ var lpAssetsJsPath_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lpAssetsJsPath/utils.js */ "./assets/src/js/utils.js");
16 16 /* harmony import */ var sweetalert2__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! sweetalert2 */ "./node_modules/sweetalert2/dist/sweetalert2.all.js");
17 17 /* harmony import */ var sweetalert2__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(sweetalert2__WEBPACK_IMPORTED_MODULE_1__);
18 18 /* harmony import */ var lpAssetsJsPath_lpToastify_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! lpAssetsJsPath/lpToastify.js */ "./assets/src/js/lpToastify.js");
19 -/**
20 - * Create course with AI
19 +/**
20 + * Create course with AI
21 21 */
22 22
23 23
24 24
@@ -103,10 +103,10 @@
103 103 sweetalert2__WEBPACK_IMPORTED_MODULE_1___default().close();
104 104 }
105 105
106 106 // Testing custom confirm box
107 - /*if ( confirm( message ) ) {
108 - SweetAlert.close();
107 + /*if ( confirm( message ) ) {
108 + SweetAlert.close();
109 109 }*/
110 110 }
111 111 }]);
112 112 }
@@ -211,11 +211,11 @@
211 211 }
212 212 });
213 213 }
214 214
215 - /**
216 - * Create prompt from data config
217 - * @param args
215 + /**
216 + * Create prompt from data config
217 + * @param args
218 218 */
219 219 generatePrompt(args) {
220 220 const {
221 221 e,
@@ -254,11 +254,11 @@
254 254 };
255 255 window.lpAJAXG.fetchAJAX(dataSend, callBack);
256 256 }
257 257
258 - /**
259 - * Submit prompt to OpenAI to generate course data
260 - * @param args
258 + /**
259 + * Submit prompt to OpenAI to generate course data
260 + * @param args
261 261 */
262 262 generateDataCourse(args) {
263 263 const {
264 264 e,
@@ -308,11 +308,11 @@
308 308 lp_is_generating_course_data = true;
309 309 window.lpAJAXG.fetchAJAX(dataSend, callBack);
310 310 }
311 311
312 - /**
313 - * Create course with data of OpenAI
314 - * @param args
312 + /**
313 + * Create course with data of OpenAI
314 + * @param args
315 315 */
316 316 createCourse(args) {
317 317 const {
318 318 e,
@@ -418,9 +418,8 @@
418 418 if (!btn) {
419 419 return;
420 420 }
421 421 lpAssetsJsPath_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpSetLoadingEl(btn, isLoading ? 1 : 0);
422 - btn.disabled = !!isLoading;
423 422 }
424 423 init() {
425 424 if (ViewStudentsModal._loadedEvents) {
426 425 return;
@@ -456,9 +455,9 @@
456 455 }]);
457 456 }
458 457 handleOpenModal(args) {
459 458 const btn = args?.target?.closest(ViewStudentsModal.selectors.courseTrigger);
460 - if (!btn || this.isRequesting || btn.classList.contains('loading') || btn.disabled) {
459 + if (!btn || this.isRequesting || btn.classList.contains('loading')) {
461 460 return;
462 461 }
463 462 const courseId = parseInt(btn.dataset.courseId, 10) || 0;
464 463 if (!courseId) {
@@ -508,9 +507,9 @@
508 507 }
509 508 if (args?.e) {
510 509 args.e.preventDefault();
511 510 }
512 - if (this.isRequesting || btn.classList.contains('loading') || btn.disabled) {
511 + if (this.isRequesting || btn.classList.contains('loading')) {
513 512 return;
514 513 }
515 514 form.reset();
516 515 this.setButtonLoadingState(btn, true);
@@ -662,16 +661,16 @@
662 661 /* harmony export */ });
663 662 /* harmony import */ var toastify_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! toastify-js */ "./node_modules/toastify-js/src/toastify.js");
664 663 /* harmony import */ var toastify_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(toastify_js__WEBPACK_IMPORTED_MODULE_0__);
665 664 /* harmony import */ var toastify_js_src_toastify_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! toastify-js/src/toastify.css */ "./node_modules/toastify-js/src/toastify.css");
666 -/**
667 - * Utils functions
668 - *
669 - * @param url
670 - * @param data
671 - * @param functions
672 - * @since 4.3.0
673 - * @version 1.0.0
665 +/**
666 + * Utils functions
667 + *
668 + * @param url
669 + * @param data
670 + * @param functions
671 + * @since 4.3.0
672 + * @version 1.0.0
674 673 */
675 674
676 675
677 676 const argsToastify = {
@@ -713,8 +712,9 @@
713 712 __webpack_require__.r(__webpack_exports__);
714 713 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
715 714 /* harmony export */ debounce: () => (/* binding */ debounce),
716 715 /* harmony export */ eventHandlers: () => (/* binding */ eventHandlers),
716 +/* harmony export */ fullScreenView: () => (/* binding */ fullScreenView),
717 717 /* harmony export */ getDataOfForm: () => (/* binding */ getDataOfForm),
718 718 /* harmony export */ getFieldKeysOfForm: () => (/* binding */ getFieldKeysOfForm),
719 719 /* harmony export */ listenElementCreated: () => (/* binding */ listenElementCreated),
720 720 /* harmony export */ listenElementViewed: () => (/* binding */ listenElementViewed),
@@ -726,18 +726,19 @@
726 726 /* harmony export */ lpOnElementReady: () => (/* binding */ lpOnElementReady),
727 727 /* harmony export */ lpSetLoadingEl: () => (/* binding */ lpSetLoadingEl),
728 728 /* harmony export */ lpShowHideEl: () => (/* binding */ lpShowHideEl),
729 729 /* harmony export */ mergeDataWithDatForm: () => (/* binding */ mergeDataWithDatForm),
730 -/* harmony export */ toggleCollapse: () => (/* binding */ toggleCollapse)
730 +/* harmony export */ toggleCollapse: () => (/* binding */ toggleCollapse),
731 +/* harmony export */ toggleEnable: () => (/* binding */ toggleEnable)
731 732 /* harmony export */ });
732 -/**
733 - * Utils functions
734 - *
735 - * @param url
736 - * @param data
737 - * @param functions
738 - * @since 4.2.5.1
739 - * @version 1.0.6
733 +/**
734 + * Utils functions
735 + *
736 + * @param url
737 + * @param data
738 + * @param functions
739 + * @since 4.2.5.1
740 + * @version 1.0.7
740 741 */
741 742 const lpClassName = {
742 743 hidden: 'lp-hidden',
743 744 loading: 'loading',
@@ -742,9 +743,12 @@
742 743 hidden: 'lp-hidden',
743 744 loading: 'loading',
744 745 elCollapse: 'lp-collapse',
745 746 elSectionToggle: '.lp-section-toggle',
746 - elTriggerToggle: '.lp-trigger-toggle'
747 + elTriggerToggle: '.lp-trigger-toggle',
748 + elBtnFullScreen: '.lp-btn-full-screen-view',
749 + elFullScreen: 'lp-full-screen-view',
750 + elBtnFullScreenClose: 'lp-full-screen-view__close'
747 751 };
748 752 const lpFetchAPI = (url, data = {}, functions = {}) => {
749 753 if ('function' === typeof functions.before) {
750 754 functions.before();
@@ -766,12 +770,12 @@
766 770 }
767 771 });
768 772 };
769 773
770 -/**
771 - * Get current URL without params.
772 - *
773 - * @since 4.2.5.1
774 +/**
775 + * Get current URL without params.
776 + *
777 + * @since 4.2.5.1
774 778 */
775 779 const lpGetCurrentURLNoParam = () => {
776 780 let currentUrl = window.location.href;
777 781 const hasParams = currentUrl.includes('?');
@@ -787,14 +791,14 @@
787 791 });
788 792 return url;
789 793 };
790 794
791 -/**
792 - * Listen element viewed.
793 - *
794 - * @param el
795 - * @param callback
796 - * @since 4.2.5.8
795 +/**
796 + * Listen element viewed.
797 + *
798 + * @param el
799 + * @param callback
800 + * @since 4.2.5.8
797 801 */
798 802 const listenElementViewed = (el, callback) => {
799 803 const observerSeeItem = new IntersectionObserver(function (entries) {
800 804 for (const entry of entries) {
@@ -805,13 +809,13 @@
805 809 });
806 810 observerSeeItem.observe(el);
807 811 };
808 812
809 -/**
810 - * Listen element created.
811 - *
812 - * @param callback
813 - * @since 4.2.5.8
813 +/**
814 + * Listen element created.
815 + *
816 + * @param callback
817 + * @since 4.2.5.8
814 818 */
815 819 const listenElementCreated = callback => {
816 820 const observerCreateItem = new MutationObserver(function (mutations) {
817 821 mutations.forEach(function (mutation) {
@@ -830,14 +834,14 @@
830 834 });
831 835 // End.
832 836 };
833 837
834 -/**
835 - * Listen element created.
836 - *
837 - * @param selector
838 - * @param callback
839 - * @since 4.2.7.1
838 +/**
839 + * Listen element created.
840 + *
841 + * @param selector
842 + * @param callback
843 + * @since 4.2.7.1
840 844 */
841 845 const lpOnElementReady = (selector, callback) => {
842 846 const element = document.querySelector(selector);
843 847 if (element) {
@@ -978,17 +982,17 @@
978 982 };
979 983 return dataHandle;
980 984 };
981 985
982 -/**
983 - * Event trigger
984 - * For each list of event handlers, listen event on document.
985 - *
986 - * eventName: 'click', 'change', ...
987 - * eventHandlers = [ { selector: '.lp-button', callBack: function(){}, class: object } ]
988 - *
989 - * @param eventName
990 - * @param eventHandlers
986 +/**
987 + * Event trigger
988 + * For each list of event handlers, listen event on document.
989 + *
990 + * eventName: 'click', 'change', ...
991 + * eventHandlers = [ { selector: '.lp-button', callBack: function(){}, class: object } ]
992 + *
993 + * @param eventName
994 + * @param eventHandlers
991 995 */
992 996 const eventHandlers = (eventName, eventHandlers) => {
993 997 document.addEventListener(eventName, e => {
994 998 const target = e.target;
@@ -1029,32 +1033,32 @@
1029 1033 });
1030 1034 });
1031 1035 };
1032 1036
1033 -/**
1034 - * Debounce - delays function execution until after `wait` ms of inactivity.
1035 - *
1036 - * Each call resets the timer. Only the last call in a burst executes.
1037 - *
1038 - * USE CASES:
1039 - * - Search inputs, form validation, window resize
1040 - * - Multiple elements need independent timers
1041 - * - When you need to call with different arguments
1042 - *
1043 - * EXAMPLES:
1044 - * const debouncedSearch = debounce( (query) => fetchResults(query), 300 );
1045 - * searchInput.addEventListener('input', (e) => debouncedSearch(e.target.value));
1046 - *
1047 - * const debouncedResize = debounce( recalculateLayout, 250 );
1048 - * window.addEventListener('resize', debouncedResize);
1049 - *
1050 - * ⚠️ Create ONCE outside event handlers, not inside.
1051 - *
1052 - * @param {Function} func - Function to debounce (can be anonymous)
1053 - * @param {number} wait - Milliseconds to wait (default: 500)
1054 - * @return {Function} Debounced wrapper function
1055 - * @since 4.3.7
1056 - * @version 1.0.0
1037 +/**
1038 + * Debounce - delays function execution until after `wait` ms of inactivity.
1039 + *
1040 + * Each call resets the timer. Only the last call in a burst executes.
1041 + *
1042 + * USE CASES:
1043 + * - Search inputs, form validation, window resize
1044 + * - Multiple elements need independent timers
1045 + * - When you need to call with different arguments
1046 + *
1047 + * EXAMPLES:
1048 + * const debouncedSearch = debounce( (query) => fetchResults(query), 300 );
1049 + * searchInput.addEventListener('input', (e) => debouncedSearch(e.target.value));
1050 + *
1051 + * const debouncedResize = debounce( recalculateLayout, 250 );
1052 + * window.addEventListener('resize', debouncedResize);
1053 + *
1054 + * ⚠️ Create ONCE outside event handlers, not inside.
1055 + *
1056 + * @param {Function} func - Function to debounce (can be anonymous)
1057 + * @param {number} wait - Milliseconds to wait (default: 500)
1058 + * @return {Function} Debounced wrapper function
1059 + * @since 4.3.7
1060 + * @version 1.0.0
1057 1061 */
1058 1062 const debounce = (func, wait = 500) => {
1059 1063 let timer;
1060 1064 return args => {
@@ -1062,8 +1066,141 @@
1062 1066 timer = setTimeout(() => func(args), wait);
1063 1067 };
1064 1068 };
1065 1069
1070 +/**
1071 + * Initialize lp-toggle-enable components.
1072 + *
1073 + * Finds all `.lp-toggle-enable` elements and wires up toggle behavior.
1074 + * Reads initial state from `data-enabled` attribute ("true"/"false").
1075 + * Calls `data-on-toggle` callback (if provided via options) on state change.
1076 + *
1077 + * HTML structure:
1078 + * <label class="lp-toggle-enable" data-enabled="true">
1079 + * <input type="checkbox" class="lp-toggle-enable__input" />
1080 + * <span class="lp-toggle-enable__track"></span>
1081 + * </label>
1082 + *
1083 + * @param {string} selector CSS selector for toggle elements (default: '.lp-toggle-enable')
1084 + * @param {Function} onToggle Optional callback( el, isEnabled ) called on state change
1085 + * @since 4.4.5
1086 + * @version 1.0.0
1087 + */
1088 +window.lpToggleEnableInit = 0;
1089 +const toggleEnable = (onToggle = null) => {
1090 + if (window.lpToggleEnableInit) {
1091 + return;
1092 + }
1093 + window.lpToggleEnableInit = 1;
1094 + const selector = '.lp-toggle-enable';
1095 + const updateUI = (toggle, isEnabled) => {
1096 + toggle.classList.toggle('is-enabled', isEnabled);
1097 + const input = toggle.querySelector('.lp-toggle-enable__input');
1098 + if (input) {
1099 + input.checked = isEnabled;
1100 + input.value = isEnabled ? '1' : '0';
1101 + }
1102 + };
1103 +
1104 + // Delegate click handling via eventHandlers.
1105 + eventHandlers('click', [{
1106 + selector,
1107 + callBack: args => {
1108 + const {
1109 + e,
1110 + target
1111 + } = args;
1112 + const toggle = target.closest(selector);
1113 + if (!toggle || toggle.classList.contains('is-disabled')) {
1114 + return;
1115 + }
1116 + e.preventDefault();
1117 + const isEnabled = !toggle.classList.contains('is-enabled');
1118 + updateUI(toggle, isEnabled);
1119 + if ('function' === typeof onToggle) {
1120 + onToggle(toggle, isEnabled);
1121 + }
1122 + }
1123 + }]);
1124 +};
1125 +
1126 +/**
1127 + * Initialize custom fullscreen view buttons.
1128 + *
1129 + * Delegates clicks on `.lp-btn-full-screen-view` buttons to
1130 + * `lpToggleFullscreenView`. Reads the `data-target` attribute to find the
1131 + * target element. Falls back to the button's parent element when
1132 + * `data-target` is not provided.
1133 + *
1134 + * @since 4.4.5
1135 + * @version 1.0.0
1136 + */
1137 +window.lpFullScreenViewInit = 0;
1138 +const fullScreenView = () => {
1139 + if (window.lpFullScreenViewInit) {
1140 + return;
1141 + }
1142 + window.lpFullScreenViewInit = 1;
1143 + let lastScrollY = 0;
1144 + const lpToggleFullscreenView = (elTarget, elBtnFullScreen = null) => {
1145 + const isFullscreen = elTarget.classList.contains(lpClassName.elFullScreen);
1146 + if (isFullscreen) {
1147 + elTarget.classList.remove(lpClassName.elFullScreen);
1148 + document.documentElement.classList.remove('lp-full-screen-active');
1149 + window.scrollTo(0, lastScrollY);
1150 + } else {
1151 + lastScrollY = window.scrollY;
1152 + elTarget.classList.add(lpClassName.elFullScreen);
1153 + document.documentElement.classList.add('lp-full-screen-active');
1154 + }
1155 + if (!isFullscreen) {
1156 + if (!elTarget.querySelector(`.${lpClassName.elBtnFullScreenClose}`)) {
1157 + const closeButton = document.createElement('button');
1158 + closeButton.type = 'button';
1159 + closeButton.className = lpClassName.elBtnFullScreenClose;
1160 + closeButton.setAttribute('aria-label', 'Close');
1161 + closeButton.innerHTML = lpData.i18n.closeButtonFullScreen || 'Close &times;';
1162 + closeButton.addEventListener('click', e => {
1163 + e.preventDefault();
1164 + lpToggleFullscreenView(elTarget);
1165 + });
1166 + elTarget.appendChild(closeButton);
1167 + }
1168 + } else {
1169 + const closeButton = elTarget.querySelector(`.${lpClassName.elBtnFullScreenClose}`);
1170 + if (closeButton) {
1171 + closeButton.remove();
1172 + }
1173 + }
1174 + };
1175 + eventHandlers('click', [{
1176 + selector: lpClassName.elBtnFullScreen,
1177 + callBack: args => {
1178 + const {
1179 + e,
1180 + target
1181 + } = args;
1182 + const elBtnFullScreen = target.closest(lpClassName.elBtnFullScreen);
1183 + if (!elBtnFullScreen) {
1184 + console.log('No full screen button found');
1185 + return;
1186 + }
1187 + e.preventDefault();
1188 + let elTarget = null;
1189 + const targetSelector = elBtnFullScreen.dataset.targetFullscreen;
1190 + console.log(targetSelector);
1191 + if (targetSelector) {
1192 + elTarget = document.querySelector(targetSelector);
1193 + }
1194 + if (!elTarget) {
1195 + console.log('No target element found');
1196 + return;
1197 + }
1198 + lpToggleFullscreenView(elTarget, elBtnFullScreen);
1199 + }
1200 + }]);
1201 +};
1202 +
1066 1203 /***/ },
1067 1204
1068 1205 /***/ "./node_modules/css-loader/dist/cjs.js!./node_modules/toastify-js/src/toastify.css"
1069 1206 /*!*****************************************************************************************!*\
@@ -7002,13 +7139,13 @@
7002 7139 \**********************************************/
7003 7140 __webpack_require__.r(__webpack_exports__);
7004 7141 /* harmony import */ var _courses_generate_with_ai_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./courses/generate-with-ai.js */ "./assets/src/js/admin/courses/generate-with-ai.js");
7005 7142 /* harmony import */ var _courses_view_students_modal_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./courses/view-students-modal.js */ "./assets/src/js/admin/courses/view-students-modal.js");
7006 -/**
7007 - * Admin Courses JS
7008 - *
7009 - * @since 4.3.0
7010 - * @version 1.0.1
7143 +/**
7144 + * Admin Courses JS
7145 + *
7146 + * @since 4.3.0
7147 + * @version 1.0.1
7011 7148 */
7012 7149
7013 7150
7014 7151