PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.3.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.3.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 4.2.0 All 139 releases
learnpress / assets / js / dist / frontend / courses.js

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

1,100 lines 35.2 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 apiAddons: lp_rest_url + 'lp/v1/addon/all',
29 apiAddonAction: lp_rest_url + 'lp/v1/addon/action-n',
30 apiAddonsPurchase: lp_rest_url + 'lp/v1/addon/info-addons-purchase',
31 apiSearchCourses: lp_rest_url + 'lp/v1/admin/tools/search-course',
32 apiSearchUsers: lp_rest_url + 'lp/v1/admin/tools/search-user',
33 apiAssignUserCourse: lp_rest_url + 'lp/v1/admin/tools/assign-user-course',
34 apiUnAssignUserCourse: lp_rest_url + 'lp/v1/admin/tools/unassign-user-course'
35 };
36 }
37 if ('undefined' !== typeof lpData) {
38 lp_rest_url = lpData.lp_rest_url;
39 lplistAPI.frontend = {
40 apiWidgets: lp_rest_url + 'lp/v1/widgets/api',
41 apiCourses: lp_rest_url + 'lp/v1/courses/archive-course',
42 // Deprecated API, don't load from v4.3.7
43 apiAJAX: lp_rest_url + 'lp/v1/load_content_via_ajax/',
44 // Deprecated since 4.3.0
45 apiProfileCoverImage: lp_rest_url + 'lp/v1/profile/cover-image'
46 };
47 }
48 if (lp_rest_url) {
49 lplistAPI.apiCourses = lp_rest_url + 'lp/v1/courses/';
50 lplistAPI.apiEditCoursesArchiveBlock = lp_rest_url + 'lp/v1/courses/edit-archive-block';
51 lplistAPI.apiCoursesSuggest = lp_rest_url + 'lp/v1/courses/courses-suggest';
52 }
53 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (lplistAPI);
54
55 /***/ },
56
57 /***/ "./assets/src/js/utils.js"
58 /*!********************************!*\
59 !*** ./assets/src/js/utils.js ***!
60 \********************************/
61 (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
62
63 __webpack_require__.r(__webpack_exports__);
64 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
65 /* harmony export */ debounce: () => (/* binding */ debounce),
66 /* harmony export */ eventHandlers: () => (/* binding */ eventHandlers),
67 /* harmony export */ getDataOfForm: () => (/* binding */ getDataOfForm),
68 /* harmony export */ getFieldKeysOfForm: () => (/* binding */ getFieldKeysOfForm),
69 /* harmony export */ listenElementCreated: () => (/* binding */ listenElementCreated),
70 /* harmony export */ listenElementViewed: () => (/* binding */ listenElementViewed),
71 /* harmony export */ lpAddQueryArgs: () => (/* binding */ lpAddQueryArgs),
72 /* harmony export */ lpAjaxParseJsonOld: () => (/* binding */ lpAjaxParseJsonOld),
73 /* harmony export */ lpClassName: () => (/* binding */ lpClassName),
74 /* harmony export */ lpFetchAPI: () => (/* binding */ lpFetchAPI),
75 /* harmony export */ lpGetCurrentURLNoParam: () => (/* binding */ lpGetCurrentURLNoParam),
76 /* harmony export */ lpOnElementReady: () => (/* binding */ lpOnElementReady),
77 /* harmony export */ lpSetLoadingEl: () => (/* binding */ lpSetLoadingEl),
78 /* harmony export */ lpShowHideEl: () => (/* binding */ lpShowHideEl),
79 /* harmony export */ mergeDataWithDatForm: () => (/* binding */ mergeDataWithDatForm),
80 /* harmony export */ toggleCollapse: () => (/* binding */ toggleCollapse)
81 /* harmony export */ });
82 /**
83 * Utils functions
84 *
85 * @param url
86 * @param data
87 * @param functions
88 * @since 4.2.5.1
89 * @version 1.0.6
90 */
91 const lpClassName = {
92 hidden: 'lp-hidden',
93 loading: 'loading',
94 elCollapse: 'lp-collapse',
95 elSectionToggle: '.lp-section-toggle',
96 elTriggerToggle: '.lp-trigger-toggle'
97 };
98 const lpFetchAPI = (url, data = {}, functions = {}) => {
99 if ('function' === typeof functions.before) {
100 functions.before();
101 }
102 fetch(url, {
103 method: 'GET',
104 ...data
105 }).then(response => response.json()).then(response => {
106 if ('function' === typeof functions.success) {
107 functions.success(response);
108 }
109 }).catch(err => {
110 if ('function' === typeof functions.error) {
111 functions.error(err);
112 }
113 }).finally(() => {
114 if ('function' === typeof functions.completed) {
115 functions.completed();
116 }
117 });
118 };
119
120 /**
121 * Get current URL without params.
122 *
123 * @since 4.2.5.1
124 */
125 const lpGetCurrentURLNoParam = () => {
126 let currentUrl = window.location.href;
127 const hasParams = currentUrl.includes('?');
128 if (hasParams) {
129 currentUrl = currentUrl.split('?')[0];
130 }
131 return currentUrl;
132 };
133 const lpAddQueryArgs = (endpoint, args) => {
134 const url = new URL(endpoint);
135 Object.keys(args).forEach(arg => {
136 url.searchParams.set(arg, args[arg]);
137 });
138 return url;
139 };
140
141 /**
142 * Listen element viewed.
143 *
144 * @param el
145 * @param callback
146 * @since 4.2.5.8
147 */
148 const listenElementViewed = (el, callback) => {
149 const observerSeeItem = new IntersectionObserver(function (entries) {
150 for (const entry of entries) {
151 if (entry.isIntersecting) {
152 callback(entry);
153 }
154 }
155 });
156 observerSeeItem.observe(el);
157 };
158
159 /**
160 * Listen element created.
161 *
162 * @param callback
163 * @since 4.2.5.8
164 */
165 const listenElementCreated = callback => {
166 const observerCreateItem = new MutationObserver(function (mutations) {
167 mutations.forEach(function (mutation) {
168 if (mutation.addedNodes) {
169 mutation.addedNodes.forEach(function (node) {
170 if (node.nodeType === 1) {
171 callback(node);
172 }
173 });
174 }
175 });
176 });
177 observerCreateItem.observe(document, {
178 childList: true,
179 subtree: true
180 });
181 // End.
182 };
183
184 /**
185 * Listen element created.
186 *
187 * @param selector
188 * @param callback
189 * @since 4.2.7.1
190 */
191 const lpOnElementReady = (selector, callback) => {
192 const element = document.querySelector(selector);
193 if (element) {
194 callback(element);
195 return;
196 }
197 const observer = new MutationObserver((mutations, obs) => {
198 const element = document.querySelector(selector);
199 if (element) {
200 obs.disconnect();
201 callback(element);
202 }
203 });
204 observer.observe(document.documentElement, {
205 childList: true,
206 subtree: true
207 });
208 };
209
210 // Parse JSON from string with content include LP_AJAX_START.
211 const lpAjaxParseJsonOld = data => {
212 if (typeof data !== 'string') {
213 return data;
214 }
215 const m = String.raw({
216 raw: data
217 }).match(/<-- LP_AJAX_START -->(.*)<-- LP_AJAX_END -->/s);
218 try {
219 if (m) {
220 data = JSON.parse(m[1].replace(/(?:\r\n|\r|\n)/g, ''));
221 } else {
222 data = JSON.parse(data);
223 }
224 } catch (e) {
225 data = {};
226 }
227 return data;
228 };
229
230 // status 0: hide, 1: show
231 const lpShowHideEl = (el, status = 0) => {
232 if (!el) {
233 return;
234 }
235 if (!status) {
236 el.classList.add(lpClassName.hidden);
237 } else {
238 el.classList.remove(lpClassName.hidden);
239 }
240 };
241
242 // status 0: hide, 1: show
243 const lpSetLoadingEl = (el, status) => {
244 if (!el) {
245 return;
246 }
247 if (!status) {
248 el.classList.remove(lpClassName.loading);
249 } else {
250 el.classList.add(lpClassName.loading);
251 }
252 };
253
254 // Toggle collapse section
255 const toggleCollapse = (e, target, elTriggerClassName = '', elsExclude = [], callback) => {
256 if (!elTriggerClassName) {
257 elTriggerClassName = lpClassName.elTriggerToggle;
258 }
259
260 // Exclude elements, which should not trigger the collapse toggle
261 if (elsExclude && elsExclude.length > 0) {
262 for (const elExclude of elsExclude) {
263 if (target.closest(elExclude)) {
264 return;
265 }
266 }
267 }
268 const elTrigger = target.closest(elTriggerClassName);
269 if (!elTrigger) {
270 return;
271 }
272
273 //console.log( 'elTrigger', elTrigger );
274
275 const elSectionToggle = elTrigger.closest(`${lpClassName.elSectionToggle}`);
276 if (!elSectionToggle) {
277 return;
278 }
279 elSectionToggle.classList.toggle(`${lpClassName.elCollapse}`);
280 if ('function' === typeof callback) {
281 callback(elSectionToggle);
282 }
283 };
284
285 // Get data of form
286 const getDataOfForm = form => {
287 const dataSend = {};
288 const formData = new FormData(form);
289 for (const pair of formData.entries()) {
290 const key = pair[0];
291 const value = formData.getAll(key);
292 if (!dataSend.hasOwnProperty(key)) {
293 // Convert value array to string.
294 dataSend[key] = value.join(',');
295 }
296 }
297 return dataSend;
298 };
299
300 // Get field keys of form
301 const getFieldKeysOfForm = form => {
302 const keys = [];
303 const elements = form.elements;
304 for (let i = 0; i < elements.length; i++) {
305 const name = elements[i].name;
306 if (name && !keys.includes(name)) {
307 keys.push(name);
308 }
309 }
310 return keys;
311 };
312
313 // Merge data handle with data form.
314 const mergeDataWithDatForm = (elForm, dataHandle) => {
315 const dataForm = getDataOfForm(elForm);
316 const keys = getFieldKeysOfForm(elForm);
317 keys.forEach(key => {
318 if (!dataForm.hasOwnProperty(key)) {
319 delete dataHandle[key];
320 } else if (dataForm[key][0] === '') {
321 delete dataForm[key];
322 delete dataHandle[key];
323 }
324 });
325 dataHandle = {
326 ...dataHandle,
327 ...dataForm
328 };
329 return dataHandle;
330 };
331
332 /**
333 * Event trigger
334 * For each list of event handlers, listen event on document.
335 *
336 * eventName: 'click', 'change', ...
337 * eventHandlers = [ { selector: '.lp-button', callBack: function(){}, class: object } ]
338 *
339 * @param eventName
340 * @param eventHandlers
341 */
342 const eventHandlers = (eventName, eventHandlers) => {
343 document.addEventListener(eventName, e => {
344 const target = e.target;
345 let args = {
346 e,
347 target
348 };
349 eventHandlers.forEach(eventHandler => {
350 args = {
351 ...args,
352 ...eventHandler
353 };
354
355 //console.log( args );
356
357 // Check condition before call back
358 if (eventHandler.conditionBeforeCallBack) {
359 if (eventHandler.conditionBeforeCallBack(args) !== true) {
360 return;
361 }
362 }
363
364 // Special check for keydown event with checkIsEventEnter = true
365 if (eventName === 'keydown' && eventHandler.checkIsEventEnter) {
366 if (e.key !== 'Enter') {
367 return;
368 }
369 }
370 if (target.closest(eventHandler.selector)) {
371 if (eventHandler.class) {
372 // Call method of class, function callBack will understand exactly {this} is class object.
373 eventHandler.class[eventHandler.callBack](args);
374 } else {
375 // For send args is objected, {this} is eventHandler object, not class object.
376 eventHandler.callBack(args);
377 }
378 }
379 });
380 });
381 };
382
383 /**
384 * Debounce - delays function execution until after `wait` ms of inactivity.
385 *
386 * Each call resets the timer. Only the last call in a burst executes.
387 *
388 * USE CASES:
389 * - Search inputs, form validation, window resize
390 * - Multiple elements need independent timers
391 * - When you need to call with different arguments
392 *
393 * EXAMPLES:
394 * const debouncedSearch = debounce( (query) => fetchResults(query), 300 );
395 * searchInput.addEventListener('input', (e) => debouncedSearch(e.target.value));
396 *
397 * const debouncedResize = debounce( recalculateLayout, 250 );
398 * window.addEventListener('resize', debouncedResize);
399 *
400 * ⚠️ Create ONCE outside event handlers, not inside.
401 *
402 * @param {Function} func - Function to debounce (can be anonymous)
403 * @param {number} wait - Milliseconds to wait (default: 500)
404 * @return {Function} Debounced wrapper function
405 * @since 4.3.7
406 * @version 1.0.0
407 */
408 const debounce = (func, wait = 500) => {
409 let timer;
410 return args => {
411 clearTimeout(timer);
412 timer = setTimeout(() => func(args), wait);
413 };
414 };
415
416 /***/ },
417
418 /***/ "./assets/src/js/utils/cookies.js"
419 /*!****************************************!*\
420 !*** ./assets/src/js/utils/cookies.js ***!
421 \****************************************/
422 (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
423
424 __webpack_require__.r(__webpack_exports__);
425 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
426 /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
427 /* harmony export */ });
428 const Cookies = {
429 get: (name, def, global) => {
430 let ret;
431 if (global) {
432 ret = wpCookies.get(name);
433 } else {
434 let ck = wpCookies.get('LP');
435 if (ck) {
436 ck = JSON.parse(ck);
437 ret = name ? ck[name] : ck;
438 }
439 }
440 if (!ret && ret !== def) {
441 ret = def;
442 }
443 return ret;
444 },
445 set(name, value, expires, path, domain, secure) {
446 if (arguments.length > 2) {
447 wpCookies.set(name, value, expires, path, domain, secure);
448 } else if (arguments.length == 2) {
449 let ck = wpCookies.get('LP');
450 if (ck) {
451 ck = JSON.parse(ck);
452 } else {
453 ck = {};
454 }
455 ck[name] = value;
456 wpCookies.set('LP', JSON.stringify(ck), '', '/');
457 } else {
458 wpCookies.set('LP', JSON.stringify(name), '', '/');
459 }
460 },
461 remove(name) {
462 const allCookies = Cookies.get();
463 const reg = new RegExp(name, 'g');
464 const newCookies = {};
465 const useRegExp = name.match(/\*/);
466 for (const i in allCookies) {
467 if (useRegExp) {
468 if (!i.match(reg)) {
469 newCookies[i] = allCookies[i];
470 }
471 } else if (name != i) {
472 newCookies[i] = allCookies[i];
473 }
474 }
475 Cookies.set(newCookies);
476 }
477 };
478 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Cookies);
479
480 /***/ }
481
482 /******/ });
483 /************************************************************************/
484 /******/ // The module cache
485 /******/ var __webpack_module_cache__ = {};
486 /******/
487 /******/ // The require function
488 /******/ function __webpack_require__(moduleId) {
489 /******/ // Check if module is in cache
490 /******/ var cachedModule = __webpack_module_cache__[moduleId];
491 /******/ if (cachedModule !== undefined) {
492 /******/ return cachedModule.exports;
493 /******/ }
494 /******/ // Create a new module (and put it into the cache)
495 /******/ var module = __webpack_module_cache__[moduleId] = {
496 /******/ // no module.id needed
497 /******/ // no module.loaded needed
498 /******/ exports: {}
499 /******/ };
500 /******/
501 /******/ // Execute the module function
502 /******/ if (!(moduleId in __webpack_modules__)) {
503 /******/ delete __webpack_module_cache__[moduleId];
504 /******/ var e = new Error("Cannot find module '" + moduleId + "'");
505 /******/ e.code = 'MODULE_NOT_FOUND';
506 /******/ throw e;
507 /******/ }
508 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
509 /******/
510 /******/ // Return the exports of the module
511 /******/ return module.exports;
512 /******/ }
513 /******/
514 /************************************************************************/
515 /******/ /* webpack/runtime/define property getters */
516 /******/ (() => {
517 /******/ // define getter functions for harmony exports
518 /******/ __webpack_require__.d = (exports, definition) => {
519 /******/ for(var key in definition) {
520 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
521 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
522 /******/ }
523 /******/ }
524 /******/ };
525 /******/ })();
526 /******/
527 /******/ /* webpack/runtime/hasOwnProperty shorthand */
528 /******/ (() => {
529 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
530 /******/ })();
531 /******/
532 /******/ /* webpack/runtime/make namespace object */
533 /******/ (() => {
534 /******/ // define __esModule on exports
535 /******/ __webpack_require__.r = (exports) => {
536 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
537 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
538 /******/ }
539 /******/ Object.defineProperty(exports, '__esModule', { value: true });
540 /******/ };
541 /******/ })();
542 /******/
543 /************************************************************************/
544 var __webpack_exports__ = {};
545 // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
546 (() => {
547 /*!*******************************************!*\
548 !*** ./assets/src/js/frontend/courses.js ***!
549 \*******************************************/
550 __webpack_require__.r(__webpack_exports__);
551 /* harmony import */ var _api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../api */ "./assets/src/js/api.js");
552 /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils */ "./assets/src/js/utils.js");
553 /* harmony import */ var _utils_cookies__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../utils/cookies */ "./assets/src/js/utils/cookies.js");
554 /**
555 * @deprecated 4.2.5.8
556 * But still support for theme has html old, override.
557 * Todo: if want remove file, need to check theme override file archive, can via remove hook override file.
558 */
559
560
561
562
563 const elListCoursesIdNewDefault = '.lp-list-courses-default';
564 if ('undefined' === typeof lpData || 'undefined' === typeof lpSettingCourses) {
565 console.log('lpData || lpSettingCourses is undefined');
566 }
567
568 // Call API load courses.
569 // When LP v4.2.3.3 release a long time, we will remove this function on theme Eduma.
570 // assets/js/thim-course-filter-v2.js
571 window.lpArchiveRequestCourse = args => {
572 window.lpCourseList.updateEventTypeBeforeFetch('filter');
573 window.lpCourseList.triggerFetchAPI(args);
574 };
575
576 // Events
577 document.addEventListener('change', function (e) {
578 const target = e.target;
579 if (window.lpCourseList.checkIsNewListCourses()) {
580 return;
581 }
582 window.lpCourseList.onChangeSortBy(e, target);
583 window.lpCourseList.onChangeTypeLayout(e, target);
584 });
585 document.addEventListener('click', function (e) {
586 const target = e.target;
587 if (window.lpCourseList.checkIsNewListCourses()) {
588 return;
589 }
590 window.lpCourseList.clickLoadMore(e, target);
591 window.lpCourseList.clickNumberPage(e, target);
592 });
593 document.addEventListener('scroll', function (e) {
594 const target = e.target;
595 if (window.lpCourseList.checkIsNewListCourses()) {
596 return;
597 }
598 window.lpCourseList.scrollInfinite(e, target);
599 });
600 document.addEventListener('keyup', function (e) {
601 const target = e.target;
602 if (window.lpCourseList.checkIsNewListCourses()) {
603 return;
604 }
605 window.lpCourseList.searchCourse(e, target);
606 });
607 document.addEventListener('submit', function (e) {
608 const target = e.target;
609 if (window.lpCourseList.checkIsNewListCourses()) {
610 return;
611 }
612 window.lpCourseList.searchCourse(e, target);
613 });
614 window.lpCourseList = (() => {
615 const classArchiveCourse = 'lp-archive-courses';
616 const classListCourse = 'learn-press-courses';
617 const classPaginationCourse = 'learn-press-pagination';
618 const classSkeletonArchiveCourse = 'lp-archive-course-skeleton';
619 const classCoursesPageResult = 'courses-page-result';
620 const lpArchiveLoadAjax = parseInt(lpSettingCourses.lpArchiveLoadAjax || 0);
621 const lpArchiveNoLoadAjaxFirst = parseInt(lpSettingCourses.lpArchiveNoLoadAjaxFirst) === 1;
622 const lpArchiveSkeletonParam = lpData.urlParams || [];
623 const currentUrl = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.lpGetCurrentURLNoParam)();
624 let filterCourses = {};
625 const typePagination = lpSettingCourses.lpArchivePaginationType || 'number';
626 let typeEventBeforeFetch;
627 let timeOutSearch;
628 let isLoadingInfinite = false;
629 const fetchAPI = (args, callBack = {}) => {
630 //console.log( 'Fetch API Courses' );
631 const url = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.lpAddQueryArgs)(_api__WEBPACK_IMPORTED_MODULE_0__["default"].frontend.apiCourses, args);
632 let paramsFetch = {};
633 if (0 !== parseInt(lpData.user_id)) {
634 paramsFetch = {
635 headers: {
636 'X-WP-Nonce': lpData.nonce
637 }
638 };
639 }
640 (0,_utils__WEBPACK_IMPORTED_MODULE_1__.lpFetchAPI)(url, paramsFetch, callBack);
641 };
642 return {
643 init: () => {
644 const urlParams = {};
645 const urlQueryString = window.location.search;
646 const urlSearchParams = new URLSearchParams(urlQueryString);
647 for (const [key, val] of urlSearchParams.entries()) {
648 urlParams[key] = val;
649 }
650 filterCourses = {
651 ...lpArchiveSkeletonParam,
652 ...urlParams
653 };
654 filterCourses.paged = parseInt(filterCourses.paged || 1);
655 if (isNaN(filterCourses.paged)) {
656 filterCourses.paged = 1;
657 }
658 if (lpArchiveNoLoadAjaxFirst && typePagination !== 'number') {
659 filterCourses.paged = 1;
660 }
661 window.localStorage.setItem('lp_filter_courses', JSON.stringify(filterCourses));
662 },
663 updateEventTypeBeforeFetch: type => {
664 typeEventBeforeFetch = type;
665 },
666 onChangeSortBy: (e, target) => {
667 if (!target.classList.contains('courses-order-by')) {
668 return;
669 }
670 e.preventDefault();
671 const filterCourses = JSON.parse(window.localStorage.getItem('lp_filter_courses')) || {};
672 filterCourses.order_by = target.value || '';
673 if ('undefined' !== typeof lpSettingCourses && lpData.is_course_archive && lpSettingCourses.lpArchiveLoadAjax) {
674 window.lpCourseList.triggerFetchAPI(filterCourses);
675 } else {
676 window.location.href = (0,_utils__WEBPACK_IMPORTED_MODULE_1__.lpAddQueryArgs)(currentUrl, filterCourses);
677 }
678 },
679 onChangeTypeLayout: (e, target) => {
680 if ('lp-switch-layout-btn' !== target.getAttribute('name')) {
681 return;
682 }
683 const elArchive = target.closest(`.${classArchiveCourse}`);
684 if (!elArchive) {
685 return;
686 }
687 const elListCourse = elArchive.querySelector(`.${classListCourse}`);
688 if (!elListCourse) {
689 return;
690 }
691 e.preventDefault();
692 const layout = target.value;
693 if (layout) {
694 elListCourse.dataset.layout = layout;
695 _utils_cookies__WEBPACK_IMPORTED_MODULE_2__["default"].set('courses-layout', layout);
696 }
697 },
698 clickNumberPage: (e, target) => {
699 if (!lpArchiveLoadAjax || parseInt(lpSettingCourses.noLoadCoursesJs)) {
700 return;
701 }
702 if (target.classList.contains('page-numbers')) {
703 const parentArchive = target.closest(`.${classArchiveCourse}`);
704 if (!parentArchive) {
705 return;
706 }
707 e.preventDefault();
708 const pageCurrent = filterCourses.paged;
709 if (target.classList.contains('prev')) {
710 filterCourses.paged = pageCurrent - 1;
711 } else if (target.classList.contains('next')) {
712 filterCourses.paged = pageCurrent + 1;
713 } else {
714 filterCourses.paged = parseInt(target.textContent);
715 }
716 typeEventBeforeFetch = 'number';
717 window.lpCourseList.triggerFetchAPI(filterCourses);
718 return;
719 }
720 const parent = target.closest('.page-numbers');
721 if (parent) {
722 e.preventDefault();
723 parent.click();
724 }
725 },
726 clickLoadMore: (e, target) => {
727 if (!target.classList.contains('courses-btn-load-more')) {
728 return;
729 }
730 const elArchive = target.closest(`.${classArchiveCourse}`);
731 if (!elArchive) {
732 return;
733 }
734 const elListCourse = elArchive.querySelector(`.${classListCourse}`);
735 if (!elListCourse) {
736 return;
737 }
738 e.preventDefault();
739 ++filterCourses.paged;
740 typeEventBeforeFetch = 'load-more';
741 window.lpCourseList.triggerFetchAPI(filterCourses);
742 },
743 scrollInfinite: (e, target) => {
744 const elArchive = document.querySelector(`.${classArchiveCourse}`);
745 if (!elArchive) {
746 return;
747 }
748 const elInfinite = elArchive.querySelector('.courses-load-infinite');
749 if (!elInfinite) {
750 return;
751 }
752
753 // Create an IntersectionObserver object.
754 const observer = new IntersectionObserver(function (entries) {
755 for (const entry of entries) {
756 // If the entry is intersecting, load the image.
757 if (entry.isIntersecting) {
758 if (isLoadingInfinite) {
759 return;
760 }
761 ++filterCourses.paged;
762 typeEventBeforeFetch = 'infinite';
763 window.lpCourseList.triggerFetchAPI(filterCourses);
764
765 //observer.unobserve( entry.target );
766 }
767 }
768 });
769 observer.observe(elInfinite);
770 },
771 triggerFetchAPI: args => {
772 // For case, click on pagination, filter.
773 const elArchive = document.querySelector(`.${classArchiveCourse}`);
774 if (!elArchive) {
775 return;
776 }
777 const elListCourse = elArchive.querySelector(`.${classListCourse}`);
778 if (!elListCourse) {
779 return;
780 }
781 filterCourses = args;
782 let callBack;
783 switch (typeEventBeforeFetch) {
784 case 'load-more':
785 callBack = window.lpCourseList.callBackPaginationTypeLoadMore(elArchive, elListCourse);
786 break;
787 case 'infinite':
788 callBack = window.lpCourseList.callBackPaginationTypeInfinite(elArchive, elListCourse);
789 break;
790 case 'custom':
791 callBack = args.customCallBack || false;
792 break;
793 case 'filter':
794 default:
795 // number
796 // Change url by params filter courses
797 //callBack = window.lpCourseList.callBackPaginationTypeNumber( elListCourse );
798 callBack = window.lpCourseList.callBackFilter(args, elArchive, elListCourse);
799 break;
800 }
801 if (!callBack) {
802 return;
803 }
804
805 //console.log( 'Args', args );
806
807 fetchAPI(args, callBack);
808 },
809 callBackFilter: (args, elArchive, elListCourse) => {
810 if (!elListCourse) {
811 return;
812 }
813 const skeleton = elListCourse.querySelector(`.${classSkeletonArchiveCourse}`);
814 return {
815 before: () => {
816 window.history.pushState('', '', (0,_utils__WEBPACK_IMPORTED_MODULE_1__.lpAddQueryArgs)(currentUrl, args));
817 window.localStorage.setItem('lp_filter_courses', JSON.stringify(args));
818 if (skeleton) {
819 skeleton.style.display = 'block';
820 }
821 },
822 success: res => {
823 // Remove all items before insert new items.
824 const elLis = elListCourse.querySelectorAll(`:not(.${classSkeletonArchiveCourse})`);
825 elLis.forEach(elLi => {
826 const parent = elLi.closest(`.${classSkeletonArchiveCourse}`);
827 if (parent) {
828 return;
829 }
830 elLi.remove();
831 });
832
833 // Insert new items.
834 elListCourse.insertAdjacentHTML('afterbegin', res.data.content || '');
835
836 // Check if Pagination exists will remove.
837 const elPagination = document.querySelector(`.${classPaginationCourse}`);
838 if (elPagination) {
839 elPagination.remove();
840 }
841
842 // Insert Pagination.
843 const pagination = res.data.pagination || '';
844 elListCourse.insertAdjacentHTML('afterend', pagination);
845
846 // Set showing results page.
847 const elCoursesPageResult = document.querySelector(`.${classCoursesPageResult}`);
848 if (elCoursesPageResult) {
849 elCoursesPageResult.innerHTML = res.data.from_to || '';
850 }
851 },
852 error: error => {
853 elListCourse.innerHTML += `<div class="lp-ajax-message error" style="display:block">${error.message || 'Error'}</div>`;
854 },
855 completed: () => {
856 if (skeleton) {
857 skeleton.style.display = 'none';
858 }
859 // Scroll to archive element
860 const optionScroll = {
861 behavior: 'smooth'
862 };
863 elListCourse.closest(`.${classArchiveCourse}`).scrollIntoView(optionScroll);
864 }
865 };
866 },
867 /*callBackPaginationTypeNumber: ( elListCourse ) => {
868 if ( ! elListCourse ) {
869 return;
870 }
871 const skeleton = elListCourse.querySelector( `.${ classSkeletonArchiveCourse }` );
872 return {
873 before: () => {
874 const urlPush = lpAddQueryArgs( currentUrl, args );
875 window.history.pushState( '', '', urlPush );
876 // Save filter courses to Storage
877 window.localStorage.setItem( 'lp_filter_courses', JSON.stringify( args ) );
878 if ( skeleton ) {
879 skeleton.style.display = 'block';
880 }
881 },
882 success: ( res ) => {
883 // Remove all items before insert new items.
884 const elLis = elListCourse.querySelectorAll( `:not(.${ classSkeletonArchiveCourse })` );
885 elLis.forEach( ( elLi ) => {
886 const parent = elLi.closest( `.${ classSkeletonArchiveCourse }` );
887 if ( parent ) {
888 return;
889 }
890 elLi.remove();
891 } );
892 // Insert new items.
893 elListCourse.insertAdjacentHTML( 'afterbegin', res.data.content || '' );
894 // Check if Pagination exists will remove.
895 const elPagination = document.querySelector( `.${ classPaginationCourse }` );
896 if ( elPagination ) {
897 elPagination.remove();
898 }
899 // Insert Pagination.
900 const pagination = res.data.pagination || '';
901 elListCourse.insertAdjacentHTML( 'afterend', pagination );
902 },
903 error: ( error ) => {
904 elListCourse.innerHTML += `<div class="lp-ajax-message error" style="display:block">${ error.message || 'Error' }</div>`;
905 },
906 completed: () => {
907 if ( skeleton ) {
908 skeleton.style.display = 'none';
909 }
910 // Scroll to archive element
911 const optionScroll = { behavior: 'smooth' };
912 elListCourse.closest( '.lp-archive-courses' ).scrollIntoView( optionScroll );
913 },
914 };
915 },*/
916 callBackPaginationTypeLoadMore: (elArchive, elListCourse) => {
917 //console.log( 'callBackPaginationTypeLoadMore' );
918 if (!elListCourse || !elArchive) {
919 return false;
920 }
921 const btnLoadMore = elArchive.querySelector('.courses-btn-load-more');
922 let elLoading;
923 if (btnLoadMore) {
924 elLoading = btnLoadMore.querySelector('.lp-loading-circle');
925 }
926 //const skeleton = document.querySelector( `.${ classSkeletonArchiveCourse }` );
927
928 return {
929 before: () => {
930 if (btnLoadMore) {
931 elLoading.classList.remove('hide');
932 btnLoadMore.setAttribute('disabled', 'disabled');
933 }
934
935 /*if ( skeleton ) {
936 skeleton.style.display = 'block';
937 }*/
938 },
939 success: res => {
940 elListCourse.insertAdjacentHTML('beforeend', res.data.content || '');
941 elListCourse.insertAdjacentHTML('afterend', res.data.pagination || '');
942
943 // Set showing results page.
944 const elCoursesPageResult = document.querySelector(`.${classCoursesPageResult}`);
945 if (elCoursesPageResult) {
946 elCoursesPageResult.innerHTML = res.data.from_to || '';
947 }
948 },
949 error: error => {
950 elListCourse.innerHTML += `<div class="lp-ajax-message error" style="display:block">${error.message || 'Error'}</div>`;
951 },
952 completed: () => {
953 if (btnLoadMore) {
954 elLoading.classList.add('hide');
955 btnLoadMore.remove();
956 }
957
958 /*if ( skeleton ) {
959 skeleton.style.display = 'none';
960 }*/
961 }
962 };
963 },
964 callBackPaginationTypeInfinite: (elArchive, elListCourse) => {
965 //console.log( 'callBackPaginationTypeInfinite' );
966 if (!elListCourse || !elListCourse) {
967 return;
968 }
969 const elInfinite = elArchive.querySelector('.courses-load-infinite');
970 if (!elInfinite) {
971 return;
972 }
973 const loading = elInfinite.querySelector('.lp-loading-circle');
974 isLoadingInfinite = true;
975 elInfinite.classList.remove('courses-load-infinite');
976 return {
977 before: () => {
978 loading.classList.remove('hide');
979 },
980 success: res => {
981 elListCourse.insertAdjacentHTML('beforeend', res.data.content || '');
982 if (res.data.pagination) {
983 elListCourse.insertAdjacentHTML('afterend', res.data.pagination || '');
984 }
985
986 // Set showing results page.
987 const elCoursesPageResult = document.querySelector(`.${classCoursesPageResult}`);
988 if (elCoursesPageResult) {
989 elCoursesPageResult.innerHTML = res.data.from_to || '';
990 }
991 },
992 error: error => {
993 elListCourse.innerHTML += `<div class="lp-ajax-message error" style="display:block">${error.message || 'Error'}</div>`;
994 },
995 completed: () => {
996 elInfinite.remove();
997 isLoadingInfinite = false;
998 }
999 };
1000 },
1001 searchCourse: (e, target) => {
1002 if ('c_search' === target.name) {
1003 e.preventDefault();
1004 const parentFormSearch = target.closest('form.search-courses');
1005 if (!parentFormSearch) {
1006 return;
1007 }
1008 const btnSearch = parentFormSearch.querySelector('button[type="submit"]');
1009 btnSearch.click();
1010 return;
1011 }
1012 if (!target.classList.contains('search-courses')) {
1013 return;
1014 }
1015 const formSearchCourses = target;
1016 e.preventDefault();
1017 const elArchive = formSearchCourses.closest(`.${classArchiveCourse}`);
1018 if (!elArchive) {
1019 return;
1020 }
1021 const elListCourse = elArchive.querySelector(`.${classListCourse}`);
1022 if (!elListCourse) {
1023 return;
1024 }
1025 const elInputSearch = formSearchCourses.querySelector('input[name=c_search]');
1026 const keyword = elInputSearch.value;
1027 if (!keyword || keyword && keyword.length > 2) {
1028 if (undefined !== timeOutSearch) {
1029 clearTimeout(timeOutSearch);
1030 }
1031 timeOutSearch = setTimeout(function () {
1032 typeEventBeforeFetch = 'filter';
1033 filterCourses.c_search = keyword;
1034 filterCourses.paged = 1;
1035 window.lpCourseList.triggerFetchAPI(filterCourses);
1036 }, 800);
1037 }
1038 },
1039 ajaxEnableLoadPage: () => {
1040 // For case enable AJAX when load page.
1041 let countTime = 0;
1042 if (!lpArchiveNoLoadAjaxFirst) {
1043 let detectedElArchive;
1044 const callBack = {
1045 success: res => {
1046 detectedElArchive = setInterval(function () {
1047 const skeleton = document.querySelector(`.${classSkeletonArchiveCourse}`);
1048 const elArchive = document.querySelector(`.${classArchiveCourse}`);
1049 let elListCourse;
1050 if (elArchive) {
1051 elListCourse = elArchive.querySelector(`.${classListCourse}`);
1052 }
1053 ++countTime;
1054 if (countTime > 5000) {
1055 clearInterval(detectedElArchive);
1056 }
1057 if (elListCourse && skeleton) {
1058 clearInterval(detectedElArchive);
1059 elListCourse.insertAdjacentHTML('afterbegin', res.data.content || '');
1060 skeleton.style.display = 'none';
1061 const pagination = res.data.pagination || '';
1062 elListCourse.insertAdjacentHTML('afterend', pagination);
1063
1064 // Set showing results page.
1065 const elCoursesPageResult = document.querySelector(`.${classCoursesPageResult}`);
1066 if (elCoursesPageResult) {
1067 elCoursesPageResult.innerHTML = res.data.from_to || '';
1068 }
1069 }
1070 }, 1);
1071 }
1072 };
1073 if ('number' !== typePagination) {
1074 filterCourses.paged = 1;
1075 }
1076 fetchAPI(filterCourses, callBack);
1077 }
1078 },
1079 getFilterParams: () => {
1080 return filterCourses;
1081 },
1082 // Check has exists new list courses.
1083 checkIsNewListCourses: () => {
1084 const elListCoursesNew = document.querySelector(elListCoursesIdNewDefault);
1085 return !!elListCoursesNew;
1086 }
1087 };
1088 })();
1089 document.addEventListener('DOMContentLoaded', function () {
1090 if (window.lpCourseList.checkIsNewListCourses()) {
1091 return;
1092 }
1093 window.lpCourseList.init();
1094 window.lpCourseList.ajaxEnableLoadPage();
1095 });
1096 })();
1097
1098 /******/ })()
1099 ;
1100 //# sourceMappingURL=courses.js.map