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
learnpress / assets / js / dist / frontend / courses-v2.js

courses-v2.js in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.9, at assets/js/dist/frontend/courses-v2.js

931 lines 28.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /******/ (() => { // webpackBootstrap
2 /******/ "use strict";
3 /******/ var __webpack_modules__ = ({
4
5 /***/ "./assets/src/js/api.js"
6 /*!******************************!*\
7 !*** ./assets/src/js/api.js ***!
8 \******************************/
9 (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
10
11 __webpack_require__.r(__webpack_exports__);
12 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
13 /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
14 /* harmony export */ });
15 /**
16 * List API on backend
17 *
18 * @since 4.2.6
19 * @version 1.0.2
20 */
21
22 const lplistAPI = {};
23 let lp_rest_url;
24 if ('undefined' !== typeof lpDataAdmin) {
25 lp_rest_url = lpDataAdmin.lp_rest_url;
26 lplistAPI.admin = {
27 // apiAdminNotice: lp_rest_url + 'lp/v1/admin/tools/admin-notices',
28 apiSearchCourses: lp_rest_url + 'lp/v1/admin/tools/search-course',
29 apiSearchUsers: lp_rest_url + 'lp/v1/admin/tools/search-user',
30 apiAssignUserCourse: lp_rest_url + 'lp/v1/admin/tools/assign-user-course',
31 apiUnAssignUserCourse: lp_rest_url + 'lp/v1/admin/tools/unassign-user-course'
32 };
33 }
34 if ('undefined' !== typeof lpData) {
35 lp_rest_url = lpData.lp_rest_url;
36 lplistAPI.frontend = {
37 apiWidgets: lp_rest_url + 'lp/v1/widgets/api',
38 apiCourses: lp_rest_url + 'lp/v1/courses/archive-course',
39 // Deprecated API, don't load from v4.3.7
40 apiAJAX: lp_rest_url + 'lp/v1/load_content_via_ajax/',
41 // Deprecated since 4.3.0
42 apiProfileCoverImage: lp_rest_url + 'lp/v1/profile/cover-image'
43 };
44 }
45 if (lp_rest_url) {
46 lplistAPI.apiCourses = lp_rest_url + 'lp/v1/courses/';
47 lplistAPI.apiEditCoursesArchiveBlock = lp_rest_url + 'lp/v1/courses/edit-archive-block';
48 lplistAPI.apiCoursesSuggest = lp_rest_url + 'lp/v1/courses/courses-suggest';
49 }
50 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (lplistAPI);
51
52 /***/ },
53
54 /***/ "./assets/src/js/utils.js"
55 /*!********************************!*\
56 !*** ./assets/src/js/utils.js ***!
57 \********************************/
58 (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
59
60 __webpack_require__.r(__webpack_exports__);
61 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
62 /* harmony export */ debounce: () => (/* binding */ debounce),
63 /* harmony export */ eventHandlers: () => (/* binding */ eventHandlers),
64 /* harmony export */ fullScreenView: () => (/* binding */ fullScreenView),
65 /* harmony export */ getDataOfForm: () => (/* binding */ getDataOfForm),
66 /* harmony export */ getFieldKeysOfForm: () => (/* binding */ getFieldKeysOfForm),
67 /* harmony export */ listenElementCreated: () => (/* binding */ listenElementCreated),
68 /* harmony export */ listenElementViewed: () => (/* binding */ listenElementViewed),
69 /* harmony export */ lpAddQueryArgs: () => (/* binding */ lpAddQueryArgs),
70 /* harmony export */ lpAjaxParseJsonOld: () => (/* binding */ lpAjaxParseJsonOld),
71 /* harmony export */ lpClassName: () => (/* binding */ lpClassName),
72 /* harmony export */ lpFetchAPI: () => (/* binding */ lpFetchAPI),
73 /* harmony export */ lpGetCurrentURLNoParam: () => (/* binding */ lpGetCurrentURLNoParam),
74 /* harmony export */ lpOnElementReady: () => (/* binding */ lpOnElementReady),
75 /* harmony export */ lpSetLoadingEl: () => (/* binding */ lpSetLoadingEl),
76 /* harmony export */ lpShowHideEl: () => (/* binding */ lpShowHideEl),
77 /* harmony export */ mergeDataWithDatForm: () => (/* binding */ mergeDataWithDatForm),
78 /* harmony export */ toggleCollapse: () => (/* binding */ toggleCollapse),
79 /* harmony export */ toggleEnable: () => (/* binding */ toggleEnable)
80 /* harmony export */ });
81 /**
82 * Utils functions
83 *
84 * @param url
85 * @param data
86 * @param functions
87 * @since 4.2.5.1
88 * @version 1.0.7
89 */
90 const lpClassName = {
91 hidden: 'lp-hidden',
92 loading: 'loading',
93 elCollapse: 'lp-collapse',
94 elSectionToggle: '.lp-section-toggle',
95 elTriggerToggle: '.lp-trigger-toggle',
96 elBtnFullScreen: '.lp-btn-full-screen-view',
97 elFullScreen: 'lp-full-screen-view',
98 elBtnFullScreenClose: 'lp-full-screen-view__close'
99 };
100 const lpFetchAPI = (url, data = {}, functions = {}) => {
101 if ('function' === typeof functions.before) {
102 functions.before();
103 }
104 fetch(url, {
105 method: 'GET',
106 ...data
107 }).then(response => response.json()).then(response => {
108 if ('function' === typeof functions.success) {
109 functions.success(response);
110 }
111 }).catch(err => {
112 if ('function' === typeof functions.error) {
113 functions.error(err);
114 }
115 }).finally(() => {
116 if ('function' === typeof functions.completed) {
117 functions.completed();
118 }
119 });
120 };
121
122 /**
123 * Get current URL without params.
124 *
125 * @since 4.2.5.1
126 */
127 const lpGetCurrentURLNoParam = () => {
128 let currentUrl = window.location.href;
129 const hasParams = currentUrl.includes('?');
130 if (hasParams) {
131 currentUrl = currentUrl.split('?')[0];
132 }
133 return currentUrl;
134 };
135 const lpAddQueryArgs = (endpoint, args) => {
136 const url = new URL(endpoint);
137 Object.keys(args).forEach(arg => {
138 url.searchParams.set(arg, args[arg]);
139 });
140 return url;
141 };
142
143 /**
144 * Listen element viewed.
145 *
146 * @param el
147 * @param callback
148 * @since 4.2.5.8
149 */
150 const listenElementViewed = (el, callback) => {
151 const observerSeeItem = new IntersectionObserver(function (entries) {
152 for (const entry of entries) {
153 if (entry.isIntersecting) {
154 callback(entry);
155 }
156 }
157 });
158 observerSeeItem.observe(el);
159 };
160
161 /**
162 * Listen element created.
163 *
164 * @param callback
165 * @since 4.2.5.8
166 */
167 const listenElementCreated = callback => {
168 const observerCreateItem = new MutationObserver(function (mutations) {
169 mutations.forEach(function (mutation) {
170 if (mutation.addedNodes) {
171 mutation.addedNodes.forEach(function (node) {
172 if (node.nodeType === 1) {
173 callback(node);
174 }
175 });
176 }
177 });
178 });
179 observerCreateItem.observe(document, {
180 childList: true,
181 subtree: true
182 });
183 // End.
184 };
185
186 /**
187 * Listen element created.
188 *
189 * @param selector
190 * @param callback
191 * @since 4.2.7.1
192 */
193 const lpOnElementReady = (selector, callback) => {
194 const element = document.querySelector(selector);
195 if (element) {
196 callback(element);
197 return;
198 }
199 const observer = new MutationObserver((mutations, obs) => {
200 const element = document.querySelector(selector);
201 if (element) {
202 obs.disconnect();
203 callback(element);
204 }
205 });
206 observer.observe(document.documentElement, {
207 childList: true,
208 subtree: true
209 });
210 };
211
212 // Parse JSON from string with content include LP_AJAX_START.
213 const lpAjaxParseJsonOld = data => {
214 if (typeof data !== 'string') {
215 return data;
216 }
217 const m = String.raw({
218 raw: data
219 }).match(/<-- LP_AJAX_START -->(.*)<-- LP_AJAX_END -->/s);
220 try {
221 if (m) {
222 data = JSON.parse(m[1].replace(/(?:\r\n|\r|\n)/g, ''));
223 } else {
224 data = JSON.parse(data);
225 }
226 } catch (e) {
227 data = {};
228 }
229 return data;
230 };
231
232 // status 0: hide, 1: show
233 const lpShowHideEl = (el, status = 0) => {
234 if (!el) {
235 return;
236 }
237 if (!status) {
238 el.classList.add(lpClassName.hidden);
239 } else {
240 el.classList.remove(lpClassName.hidden);
241 }
242 };
243
244 // status 0: hide, 1: show
245 const lpSetLoadingEl = (el, status) => {
246 if (!el) {
247 return;
248 }
249 if (!status) {
250 el.classList.remove(lpClassName.loading);
251 } else {
252 el.classList.add(lpClassName.loading);
253 }
254 };
255
256 // Toggle collapse section
257 const toggleCollapse = (e, target, elTriggerClassName = '', elsExclude = [], callback) => {
258 if (!elTriggerClassName) {
259 elTriggerClassName = lpClassName.elTriggerToggle;
260 }
261
262 // Exclude elements, which should not trigger the collapse toggle
263 if (elsExclude && elsExclude.length > 0) {
264 for (const elExclude of elsExclude) {
265 if (target.closest(elExclude)) {
266 return;
267 }
268 }
269 }
270 const elTrigger = target.closest(elTriggerClassName);
271 if (!elTrigger) {
272 return;
273 }
274
275 //console.log( 'elTrigger', elTrigger );
276
277 const elSectionToggle = elTrigger.closest(`${lpClassName.elSectionToggle}`);
278 if (!elSectionToggle) {
279 return;
280 }
281 elSectionToggle.classList.toggle(`${lpClassName.elCollapse}`);
282 if ('function' === typeof callback) {
283 callback(elSectionToggle);
284 }
285 };
286
287 // Get data of form
288 const getDataOfForm = form => {
289 const dataSend = {};
290 const formData = new FormData(form);
291 for (const pair of formData.entries()) {
292 const key = pair[0];
293 const value = formData.getAll(key);
294 if (!dataSend.hasOwnProperty(key)) {
295 // Convert value array to string.
296 dataSend[key] = value.join(',');
297 }
298 }
299 return dataSend;
300 };
301
302 // Get field keys of form
303 const getFieldKeysOfForm = form => {
304 const keys = [];
305 const elements = form.elements;
306 for (let i = 0; i < elements.length; i++) {
307 const name = elements[i].name;
308 if (name && !keys.includes(name)) {
309 keys.push(name);
310 }
311 }
312 return keys;
313 };
314
315 // Merge data handle with data form.
316 const mergeDataWithDatForm = (elForm, dataHandle) => {
317 const dataForm = getDataOfForm(elForm);
318 const keys = getFieldKeysOfForm(elForm);
319 keys.forEach(key => {
320 if (!dataForm.hasOwnProperty(key)) {
321 delete dataHandle[key];
322 } else if (dataForm[key][0] === '') {
323 delete dataForm[key];
324 delete dataHandle[key];
325 }
326 });
327 dataHandle = {
328 ...dataHandle,
329 ...dataForm
330 };
331 return dataHandle;
332 };
333
334 /**
335 * Event trigger
336 * For each list of event handlers, listen event on document.
337 *
338 * eventName: 'click', 'change', ...
339 * eventHandlers = [ { selector: '.lp-button', callBack: function(){}, class: object } ]
340 *
341 * @param eventName
342 * @param eventHandlers
343 */
344 const eventHandlers = (eventName, eventHandlers) => {
345 document.addEventListener(eventName, e => {
346 const target = e.target;
347 let args = {
348 e,
349 target
350 };
351 eventHandlers.forEach(eventHandler => {
352 args = {
353 ...args,
354 ...eventHandler
355 };
356
357 //console.log( args );
358
359 // Check condition before call back
360 if (eventHandler.conditionBeforeCallBack) {
361 if (eventHandler.conditionBeforeCallBack(args) !== true) {
362 return;
363 }
364 }
365
366 // Special check for keydown event with checkIsEventEnter = true
367 if (eventName === 'keydown' && eventHandler.checkIsEventEnter) {
368 if (e.key !== 'Enter') {
369 return;
370 }
371 }
372 if (target.closest(eventHandler.selector)) {
373 if (eventHandler.class) {
374 // Call method of class, function callBack will understand exactly {this} is class object.
375 eventHandler.class[eventHandler.callBack](args);
376 } else {
377 // For send args is objected, {this} is eventHandler object, not class object.
378 eventHandler.callBack(args);
379 }
380 }
381 });
382 });
383 };
384
385 /**
386 * Debounce - delays function execution until after `wait` ms of inactivity.
387 *
388 * Each call resets the timer. Only the last call in a burst executes.
389 *
390 * USE CASES:
391 * - Search inputs, form validation, window resize
392 * - Multiple elements need independent timers
393 * - When you need to call with different arguments
394 *
395 * EXAMPLES:
396 * const debouncedSearch = debounce( (query) => fetchResults(query), 300 );
397 * searchInput.addEventListener('input', (e) => debouncedSearch(e.target.value));
398 *
399 * const debouncedResize = debounce( recalculateLayout, 250 );
400 * window.addEventListener('resize', debouncedResize);
401 *
402 * ⚠️ Create ONCE outside event handlers, not inside.
403 *
404 * @param {Function} func - Function to debounce (can be anonymous)
405 * @param {number} wait - Milliseconds to wait (default: 500)
406 * @return {Function} Debounced wrapper function
407 * @since 4.3.7
408 * @version 1.0.0
409 */
410 const debounce = (func, wait = 500) => {
411 let timer;
412 return args => {
413 clearTimeout(timer);
414 timer = setTimeout(() => func(args), wait);
415 };
416 };
417
418 /**
419 * Initialize lp-toggle-enable components.
420 *
421 * Finds all `.lp-toggle-enable` elements and wires up toggle behavior.
422 * Reads initial state from `data-enabled` attribute ("true"/"false").
423 * Calls `data-on-toggle` callback (if provided via options) on state change.
424 *
425 * HTML structure:
426 * <label class="lp-toggle-enable" data-enabled="true">
427 * <input type="checkbox" class="lp-toggle-enable__input" />
428 * <span class="lp-toggle-enable__track"></span>
429 * </label>
430 *
431 * @param {string} selector CSS selector for toggle elements (default: '.lp-toggle-enable')
432 * @param {Function} onToggle Optional callback( el, isEnabled ) called on state change
433 * @since 4.4.5
434 * @version 1.0.0
435 */
436 window.lpToggleEnableInit = 0;
437 const toggleEnable = (onToggle = null) => {
438 if (window.lpToggleEnableInit) {
439 return;
440 }
441 window.lpToggleEnableInit = 1;
442 const selector = '.lp-toggle-enable';
443 const updateUI = (toggle, isEnabled) => {
444 toggle.classList.toggle('is-enabled', isEnabled);
445 const input = toggle.querySelector('.lp-toggle-enable__input');
446 if (input) {
447 input.checked = isEnabled;
448 input.value = isEnabled ? '1' : '0';
449 }
450 };
451
452 // Delegate click handling via eventHandlers.
453 eventHandlers('click', [{
454 selector,
455 callBack: args => {
456 const {
457 e,
458 target
459 } = args;
460 const toggle = target.closest(selector);
461 if (!toggle || toggle.classList.contains('is-disabled')) {
462 return;
463 }
464 e.preventDefault();
465 const isEnabled = !toggle.classList.contains('is-enabled');
466 updateUI(toggle, isEnabled);
467 if ('function' === typeof onToggle) {
468 onToggle(toggle, isEnabled);
469 }
470 }
471 }]);
472 };
473
474 /**
475 * Initialize custom fullscreen view buttons.
476 *
477 * Delegates clicks on `.lp-btn-full-screen-view` buttons to
478 * `lpToggleFullscreenView`. Reads the `data-target` attribute to find the
479 * target element. Falls back to the button's parent element when
480 * `data-target` is not provided.
481 *
482 * @since 4.4.5
483 * @version 1.0.0
484 */
485 window.lpFullScreenViewInit = 0;
486 const fullScreenView = () => {
487 if (window.lpFullScreenViewInit) {
488 return;
489 }
490 window.lpFullScreenViewInit = 1;
491 let lastScrollY = 0;
492 const lpToggleFullscreenView = (elTarget, elBtnFullScreen = null) => {
493 const isFullscreen = elTarget.classList.contains(lpClassName.elFullScreen);
494 if (isFullscreen) {
495 elTarget.classList.remove(lpClassName.elFullScreen);
496 document.documentElement.classList.remove('lp-full-screen-active');
497 window.scrollTo(0, lastScrollY);
498 } else {
499 lastScrollY = window.scrollY;
500 elTarget.classList.add(lpClassName.elFullScreen);
501 document.documentElement.classList.add('lp-full-screen-active');
502 }
503 if (!isFullscreen) {
504 if (!elTarget.querySelector(`.${lpClassName.elBtnFullScreenClose}`)) {
505 const closeButton = document.createElement('button');
506 closeButton.type = 'button';
507 closeButton.className = lpClassName.elBtnFullScreenClose;
508 closeButton.setAttribute('aria-label', 'Close');
509 closeButton.innerHTML = lpData.i18n.closeButtonFullScreen || 'Close &times;';
510 closeButton.addEventListener('click', e => {
511 e.preventDefault();
512 lpToggleFullscreenView(elTarget);
513 });
514 elTarget.appendChild(closeButton);
515 }
516 } else {
517 const closeButton = elTarget.querySelector(`.${lpClassName.elBtnFullScreenClose}`);
518 if (closeButton) {
519 closeButton.remove();
520 }
521 }
522 };
523 eventHandlers('click', [{
524 selector: lpClassName.elBtnFullScreen,
525 callBack: args => {
526 const {
527 e,
528 target
529 } = args;
530 const elBtnFullScreen = target.closest(lpClassName.elBtnFullScreen);
531 if (!elBtnFullScreen) {
532 console.log('No full screen button found');
533 return;
534 }
535 e.preventDefault();
536 let elTarget = null;
537 const targetSelector = elBtnFullScreen.dataset.targetFullscreen;
538 console.log(targetSelector);
539 if (targetSelector) {
540 elTarget = document.querySelector(targetSelector);
541 }
542 if (!elTarget) {
543 console.log('No target element found');
544 return;
545 }
546 lpToggleFullscreenView(elTarget, elBtnFullScreen);
547 }
548 }]);
549 };
550
551 /***/ }
552
553 /******/ });
554 /************************************************************************/
555 /******/ // The module cache
556 /******/ var __webpack_module_cache__ = {};
557 /******/
558 /******/ // The require function
559 /******/ function __webpack_require__(moduleId) {
560 /******/ // Check if module is in cache
561 /******/ var cachedModule = __webpack_module_cache__[moduleId];
562 /******/ if (cachedModule !== undefined) {
563 /******/ return cachedModule.exports;
564 /******/ }
565 /******/ // Create a new module (and put it into the cache)
566 /******/ var module = __webpack_module_cache__[moduleId] = {
567 /******/ // no module.id needed
568 /******/ // no module.loaded needed
569 /******/ exports: {}
570 /******/ };
571 /******/
572 /******/ // Execute the module function
573 /******/ if (!(moduleId in __webpack_modules__)) {
574 /******/ delete __webpack_module_cache__[moduleId];
575 /******/ var e = new Error("Cannot find module '" + moduleId + "'");
576 /******/ e.code = 'MODULE_NOT_FOUND';
577 /******/ throw e;
578 /******/ }
579 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
580 /******/
581 /******/ // Return the exports of the module
582 /******/ return module.exports;
583 /******/ }
584 /******/
585 /************************************************************************/
586 /******/ /* webpack/runtime/define property getters */
587 /******/ (() => {
588 /******/ // define getter functions for harmony exports
589 /******/ __webpack_require__.d = (exports, definition) => {
590 /******/ for(var key in definition) {
591 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
592 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
593 /******/ }
594 /******/ }
595 /******/ };
596 /******/ })();
597 /******/
598 /******/ /* webpack/runtime/hasOwnProperty shorthand */
599 /******/ (() => {
600 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
601 /******/ })();
602 /******/
603 /******/ /* webpack/runtime/make namespace object */
604 /******/ (() => {
605 /******/ // define __esModule on exports
606 /******/ __webpack_require__.r = (exports) => {
607 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
608 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
609 /******/ }
610 /******/ Object.defineProperty(exports, '__esModule', { value: true });
611 /******/ };
612 /******/ })();
613 /******/
614 /************************************************************************/
615 var __webpack_exports__ = {};
616 // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
617 (() => {
618 /*!**********************************************!*\
619 !*** ./assets/src/js/frontend/courses-v2.js ***!
620 \**********************************************/
621 __webpack_require__.r(__webpack_exports__);
622 /* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../api */ "./assets/src/js/api.js");
623 /* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils.js */ "./assets/src/js/utils.js");
624 /**
625 * Handle events for courses list.
626 *
627 * @since 4.2.5.8
628 * @version 1.0.1
629 */
630
631
632
633 if ('undefined' === typeof lpData) {
634 console.log('lpData is undefined');
635 }
636
637 // Events
638 document.addEventListener('change', function (e) {
639 const target = e.target;
640 window.lpCoursesList.onChangeSortBy(e, target);
641 window.lpCoursesList.onChangeTypeLayout(e, target);
642 });
643 document.addEventListener('click', function (e) {
644 const target = e.target;
645 window.lpCoursesList.LoadMore(e, target);
646 });
647 document.addEventListener('keyup', function (e) {
648 const target = e.target;
649 window.lpCoursesList.searchCourse(e, target);
650 });
651 document.addEventListener('submit', function (e) {
652 const target = e.target;
653
654 //window.lpCourseList.searchCourse( e, target );
655 });
656 (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpOnElementReady)('.course-filter-btn-mobile', function (el) {
657 const widgetCourseFilter = document.querySelector('.widget_course_filter');
658 if (!widgetCourseFilter) {
659 el.remove();
660 }
661 });
662 let timeOutSearch;
663 window.lpCoursesList = (() => {
664 const classListCourse = '.lp-list-courses-no-css';
665 const classLPTarget = '.lp-target';
666 const classLoadMore = 'courses-btn-load-more-no-css';
667 const classPageResult = '.courses-page-result';
668 const classLoading = '.lp-loading-no-css';
669 const urlCurrent = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpGetCurrentURLNoParam)();
670 return {
671 LoadMore: (e, target) => {
672 const btnLoadMore = target.closest(`.${classLoadMore + ':not(.disabled)'}`);
673 if (!btnLoadMore) {
674 return;
675 }
676 const elLPTarget = btnLoadMore.closest(`${classLPTarget}`);
677 if (!elLPTarget) {
678 return;
679 }
680 e.preventDefault();
681 btnLoadMore.classList.add('disabled');
682 const elLoading = btnLoadMore.querySelector(classLoading);
683 const dataObj = JSON.parse(elLPTarget.dataset.send);
684 const dataSend = {
685 ...dataObj
686 };
687 if (!dataSend.args.hasOwnProperty('paged')) {
688 dataSend.args.paged = 1;
689 }
690 dataSend.args.paged++;
691 elLPTarget.dataset.send = JSON.stringify(dataSend);
692 if (elLoading) {
693 elLoading.classList.remove('hide');
694 }
695 const callBack = {
696 success: response => {
697 const {
698 status,
699 message,
700 data
701 } = response;
702 const paged = parseInt(data.paged);
703 const totalPages = parseInt(data.total_pages);
704 const newEl = document.createElement('div');
705 newEl.innerHTML = data.content || '';
706 const elListCourse = elLPTarget.querySelector(classListCourse);
707 const elPageResult = elLPTarget.querySelector(classPageResult);
708 const elPageResultNew = newEl.querySelector(classPageResult);
709 elListCourse.insertAdjacentHTML('beforeend', newEl.querySelector(classListCourse).innerHTML);
710 if (elPageResult && elPageResultNew) {
711 elPageResult.innerHTML = elPageResultNew.innerHTML;
712 }
713 if (paged >= totalPages) {
714 btnLoadMore.remove();
715 }
716 },
717 error: error => {
718 console.log(error);
719 },
720 completed: () => {
721 //console.log( 'completed' );
722 if (elLoading) {
723 elLoading.classList.add('hide');
724 }
725 btnLoadMore.classList.remove('disabled');
726 }
727 };
728 window.lpAJAXG.fetchAJAX(dataSend, callBack);
729 },
730 LoadInfinite: () => {
731 // When see element, will call API to load more items.
732 const callBackAfterSeeItem = entry => {
733 const elInfinite = entry.target;
734 const elLoading = elInfinite.querySelector(`${classLoading}:not(.disabled)`);
735 if (!elLoading) {
736 return;
737 }
738 elLoading.classList.remove('hide');
739 elLoading.classList.add('disabled');
740 const elLPTarget = elInfinite.closest(classLPTarget);
741 if (!elLPTarget) {
742 return;
743 }
744 const dataObj = JSON.parse(elLPTarget.dataset.send);
745 const dataSend = {
746 ...dataObj
747 }; // Clone object
748
749 if (!dataSend.args.hasOwnProperty('paged')) {
750 dataSend.args.paged = 1;
751 }
752
753 // Handle set data send to call API
754 dataSend.args.paged++;
755 elLPTarget.dataset.send = JSON.stringify(dataSend);
756 const callBack = {
757 success: response => {
758 const {
759 status,
760 message,
761 data
762 } = response;
763 const newEl = document.createElement('div');
764 newEl.innerHTML = data.content || '';
765 const elListCourse = elLPTarget.querySelector(classListCourse);
766 const elPageResult = elLPTarget.querySelector(classPageResult);
767 const elPageResultNew = newEl.querySelector(classPageResult);
768 elListCourse.insertAdjacentHTML('beforeend', newEl.querySelector(classListCourse).innerHTML);
769 if (elPageResult && elPageResultNew) {
770 elPageResult.innerHTML = elPageResultNew.innerHTML;
771 }
772 if (data.total_pages === data.paged) {
773 elInfinite.remove();
774 }
775 },
776 error: error => {
777 console.log(error);
778 },
779 completed: () => {
780 //console.log( 'completed' );
781 elLoading.classList.add('hide');
782 elLoading.classList.remove('disabled');
783 }
784 };
785 window.lpAJAXG.fetchAJAX(dataSend, callBack);
786 };
787
788 // Listen el courses load infinite have just created.
789 (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.listenElementCreated)(node => {
790 if (node.classList.contains('courses-load-infinite-no-css')) {
791 (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.listenElementViewed)(node, callBackAfterSeeItem);
792 } else if (node.classList.contains('wp-block-learnpress-list-courses')) {
793 // For block Gutenberg
794 const elInfinite = node.querySelector('.courses-load-infinite-no-css');
795 if (elInfinite) {
796 (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.listenElementViewed)(elInfinite, callBackAfterSeeItem);
797 }
798 }
799 });
800
801 // If el created on DOMContentLoaded.
802 const elInfinite = document.querySelector('.courses-load-infinite-no-css');
803 if (elInfinite) {
804 (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.listenElementViewed)(elInfinite, callBackAfterSeeItem);
805 }
806 },
807 onChangeSortBy: (e, target) => {
808 if (!target.classList.contains('courses-order-by')) {
809 return;
810 }
811 const elLPTarget = target.closest(classLPTarget);
812 if (!elLPTarget) {
813 lpData.urlParams.paged = 1;
814 lpData.urlParams.order_by = target.value || '';
815 window.location.href = (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpAddQueryArgs)(urlCurrent, lpData.urlParams);
816 return;
817 }
818 e.preventDefault();
819 const dataObj = JSON.parse(elLPTarget.dataset.send);
820 const dataSend = {
821 ...dataObj
822 };
823 dataSend.args.paged = 1;
824 dataSend.args.order_by = target.value || '';
825 elLPTarget.dataset.send = JSON.stringify(dataSend);
826
827 // Set url params to reload page.
828 // Todo: need check allow set url params.
829 lpData.urlParams.paged = dataSend.args.paged;
830 lpData.urlParams.order_by = dataSend.args.order_by;
831 window.history.pushState({}, '', (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpAddQueryArgs)(urlCurrent, lpData.urlParams));
832 // End.
833
834 // Show loading
835 window.lpAJAXG.showHideLoading(elLPTarget, 1);
836 // End
837
838 const callBack = {
839 success: response => {
840 //console.log( 'response', response );
841 const {
842 status,
843 message,
844 data
845 } = response;
846 elLPTarget.innerHTML = data.content || '';
847 },
848 error: error => {
849 console.log(error);
850 },
851 completed: () => {
852 //console.log( 'completed' );
853 window.lpAJAXG.showHideLoading(elLPTarget, 0);
854 }
855 };
856 window.lpAJAXG.fetchAJAX(dataSend, callBack);
857 },
858 onChangeTypeLayout: (e, target) => {
859 if ('lp-switch-layout-btn' !== target.getAttribute('name')) {
860 return;
861 }
862 const elListCourse = document.querySelector(classListCourse);
863 if (!elListCourse) {
864 return;
865 }
866 e.preventDefault();
867 const layout = target.value;
868 if (layout) {
869 elListCourse.dataset.layout = layout;
870 window.wpCookies.set('courses-layout', layout, 24 * 60 * 60, '/');
871 }
872 },
873 searchCourse: (e, target) => {
874 if ('c_search' !== target.name) {
875 return;
876 }
877 const elLPTarget = target.closest(classLPTarget);
878 if (!elLPTarget) {
879 return;
880 }
881 e.preventDefault();
882 const dataObj = JSON.parse(elLPTarget.dataset.send);
883 const dataSend = {
884 ...dataObj
885 };
886 const keyword = target.value;
887 dataSend.args.c_search = keyword || '';
888 dataSend.args.paged = 1;
889 elLPTarget.dataset.send = JSON.stringify(dataSend);
890
891 // Set url params to reload page.
892 // Todo: need check allow set url params.
893 lpData.urlParams.paged = dataSend.args.paged;
894 lpData.urlParams.c_search = dataSend.args.c_search;
895 window.history.pushState({}, '', (0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpAddQueryArgs)((0,_utils_js__WEBPACK_IMPORTED_MODULE_1__.lpGetCurrentURLNoParam)(), lpData.urlParams));
896 // End.
897
898 if (!keyword || keyword && keyword.length > 2) {
899 if (undefined !== timeOutSearch) {
900 clearTimeout(timeOutSearch);
901 }
902 timeOutSearch = setTimeout(function () {
903 const callBack = {
904 success: response => {
905 //console.log( 'response', response );
906 const {
907 status,
908 message,
909 data
910 } = response;
911 elLPTarget.innerHTML = data.content || '';
912 },
913 error: error => {
914 console.log(error);
915 },
916 completed: () => {
917 //console.log( 'completed' );
918 }
919 };
920 window.lpAJAXG.fetchAJAX(dataSend, callBack);
921 }, 800);
922 }
923 }
924 };
925 })();
926 window.lpCoursesList.LoadInfinite();
927 })();
928
929 /******/ })()
930 ;
931 //# sourceMappingURL=courses-v2.js.map