PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.6
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.6
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 / admin / learnpress.js

learnpress.js in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.6, at assets/js/dist/admin/learnpress.js

1,319 lines 41.8 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/utils.js"
6 /*!********************************!*\
7 !*** ./assets/src/js/utils.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 */ debounce: () => (/* binding */ debounce),
14 /* harmony export */ eventHandlers: () => (/* binding */ eventHandlers),
15 /* harmony export */ fullScreenView: () => (/* binding */ fullScreenView),
16 /* harmony export */ getDataOfForm: () => (/* binding */ getDataOfForm),
17 /* harmony export */ getFieldKeysOfForm: () => (/* binding */ getFieldKeysOfForm),
18 /* harmony export */ listenElementCreated: () => (/* binding */ listenElementCreated),
19 /* harmony export */ listenElementViewed: () => (/* binding */ listenElementViewed),
20 /* harmony export */ lpAddQueryArgs: () => (/* binding */ lpAddQueryArgs),
21 /* harmony export */ lpAjaxParseJsonOld: () => (/* binding */ lpAjaxParseJsonOld),
22 /* harmony export */ lpClassName: () => (/* binding */ lpClassName),
23 /* harmony export */ lpFetchAPI: () => (/* binding */ lpFetchAPI),
24 /* harmony export */ lpGetCurrentURLNoParam: () => (/* binding */ lpGetCurrentURLNoParam),
25 /* harmony export */ lpOnElementReady: () => (/* binding */ lpOnElementReady),
26 /* harmony export */ lpSetLoadingEl: () => (/* binding */ lpSetLoadingEl),
27 /* harmony export */ lpShowHideEl: () => (/* binding */ lpShowHideEl),
28 /* harmony export */ mergeDataWithDatForm: () => (/* binding */ mergeDataWithDatForm),
29 /* harmony export */ toggleCollapse: () => (/* binding */ toggleCollapse),
30 /* harmony export */ toggleEnable: () => (/* binding */ toggleEnable)
31 /* harmony export */ });
32 /**
33 * Utils functions
34 *
35 * @param url
36 * @param data
37 * @param functions
38 * @since 4.2.5.1
39 * @version 1.0.7
40 */
41 const lpClassName = {
42 hidden: 'lp-hidden',
43 loading: 'loading',
44 elCollapse: 'lp-collapse',
45 elSectionToggle: '.lp-section-toggle',
46 elTriggerToggle: '.lp-trigger-toggle',
47 elBtnFullScreen: '.lp-btn-full-screen-view',
48 elFullScreen: 'lp-full-screen-view',
49 elBtnFullScreenClose: 'lp-full-screen-view__close'
50 };
51 const lpFetchAPI = (url, data = {}, functions = {}) => {
52 if ('function' === typeof functions.before) {
53 functions.before();
54 }
55 fetch(url, {
56 method: 'GET',
57 ...data
58 }).then(response => response.json()).then(response => {
59 if ('function' === typeof functions.success) {
60 functions.success(response);
61 }
62 }).catch(err => {
63 if ('function' === typeof functions.error) {
64 functions.error(err);
65 }
66 }).finally(() => {
67 if ('function' === typeof functions.completed) {
68 functions.completed();
69 }
70 });
71 };
72
73 /**
74 * Get current URL without params.
75 *
76 * @since 4.2.5.1
77 */
78 const lpGetCurrentURLNoParam = () => {
79 let currentUrl = window.location.href;
80 const hasParams = currentUrl.includes('?');
81 if (hasParams) {
82 currentUrl = currentUrl.split('?')[0];
83 }
84 return currentUrl;
85 };
86 const lpAddQueryArgs = (endpoint, args) => {
87 const url = new URL(endpoint);
88 Object.keys(args).forEach(arg => {
89 url.searchParams.set(arg, args[arg]);
90 });
91 return url;
92 };
93
94 /**
95 * Listen element viewed.
96 *
97 * @param el
98 * @param callback
99 * @since 4.2.5.8
100 */
101 const listenElementViewed = (el, callback) => {
102 const observerSeeItem = new IntersectionObserver(function (entries) {
103 for (const entry of entries) {
104 if (entry.isIntersecting) {
105 callback(entry);
106 }
107 }
108 });
109 observerSeeItem.observe(el);
110 };
111
112 /**
113 * Listen element created.
114 *
115 * @param callback
116 * @since 4.2.5.8
117 */
118 const listenElementCreated = callback => {
119 const observerCreateItem = new MutationObserver(function (mutations) {
120 mutations.forEach(function (mutation) {
121 if (mutation.addedNodes) {
122 mutation.addedNodes.forEach(function (node) {
123 if (node.nodeType === 1) {
124 callback(node);
125 }
126 });
127 }
128 });
129 });
130 observerCreateItem.observe(document, {
131 childList: true,
132 subtree: true
133 });
134 // End.
135 };
136
137 /**
138 * Listen element created.
139 *
140 * @param selector
141 * @param callback
142 * @since 4.2.7.1
143 */
144 const lpOnElementReady = (selector, callback) => {
145 const element = document.querySelector(selector);
146 if (element) {
147 callback(element);
148 return;
149 }
150 const observer = new MutationObserver((mutations, obs) => {
151 const element = document.querySelector(selector);
152 if (element) {
153 obs.disconnect();
154 callback(element);
155 }
156 });
157 observer.observe(document.documentElement, {
158 childList: true,
159 subtree: true
160 });
161 };
162
163 // Parse JSON from string with content include LP_AJAX_START.
164 const lpAjaxParseJsonOld = data => {
165 if (typeof data !== 'string') {
166 return data;
167 }
168 const m = String.raw({
169 raw: data
170 }).match(/<-- LP_AJAX_START -->(.*)<-- LP_AJAX_END -->/s);
171 try {
172 if (m) {
173 data = JSON.parse(m[1].replace(/(?:\r\n|\r|\n)/g, ''));
174 } else {
175 data = JSON.parse(data);
176 }
177 } catch (e) {
178 data = {};
179 }
180 return data;
181 };
182
183 // status 0: hide, 1: show
184 const lpShowHideEl = (el, status = 0) => {
185 if (!el) {
186 return;
187 }
188 if (!status) {
189 el.classList.add(lpClassName.hidden);
190 } else {
191 el.classList.remove(lpClassName.hidden);
192 }
193 };
194
195 // status 0: hide, 1: show
196 const lpSetLoadingEl = (el, status) => {
197 if (!el) {
198 return;
199 }
200 if (!status) {
201 el.classList.remove(lpClassName.loading);
202 } else {
203 el.classList.add(lpClassName.loading);
204 }
205 };
206
207 // Toggle collapse section
208 const toggleCollapse = (e, target, elTriggerClassName = '', elsExclude = [], callback) => {
209 if (!elTriggerClassName) {
210 elTriggerClassName = lpClassName.elTriggerToggle;
211 }
212
213 // Exclude elements, which should not trigger the collapse toggle
214 if (elsExclude && elsExclude.length > 0) {
215 for (const elExclude of elsExclude) {
216 if (target.closest(elExclude)) {
217 return;
218 }
219 }
220 }
221 const elTrigger = target.closest(elTriggerClassName);
222 if (!elTrigger) {
223 return;
224 }
225
226 //console.log( 'elTrigger', elTrigger );
227
228 const elSectionToggle = elTrigger.closest(`${lpClassName.elSectionToggle}`);
229 if (!elSectionToggle) {
230 return;
231 }
232 elSectionToggle.classList.toggle(`${lpClassName.elCollapse}`);
233 if ('function' === typeof callback) {
234 callback(elSectionToggle);
235 }
236 };
237
238 // Get data of form
239 const getDataOfForm = form => {
240 const dataSend = {};
241 const formData = new FormData(form);
242 for (const pair of formData.entries()) {
243 const key = pair[0];
244 const value = formData.getAll(key);
245 if (!dataSend.hasOwnProperty(key)) {
246 // Convert value array to string.
247 dataSend[key] = value.join(',');
248 }
249 }
250 return dataSend;
251 };
252
253 // Get field keys of form
254 const getFieldKeysOfForm = form => {
255 const keys = [];
256 const elements = form.elements;
257 for (let i = 0; i < elements.length; i++) {
258 const name = elements[i].name;
259 if (name && !keys.includes(name)) {
260 keys.push(name);
261 }
262 }
263 return keys;
264 };
265
266 // Merge data handle with data form.
267 const mergeDataWithDatForm = (elForm, dataHandle) => {
268 const dataForm = getDataOfForm(elForm);
269 const keys = getFieldKeysOfForm(elForm);
270 keys.forEach(key => {
271 if (!dataForm.hasOwnProperty(key)) {
272 delete dataHandle[key];
273 } else if (dataForm[key][0] === '') {
274 delete dataForm[key];
275 delete dataHandle[key];
276 }
277 });
278 dataHandle = {
279 ...dataHandle,
280 ...dataForm
281 };
282 return dataHandle;
283 };
284
285 /**
286 * Event trigger
287 * For each list of event handlers, listen event on document.
288 *
289 * eventName: 'click', 'change', ...
290 * eventHandlers = [ { selector: '.lp-button', callBack: function(){}, class: object } ]
291 *
292 * @param eventName
293 * @param eventHandlers
294 */
295 const eventHandlers = (eventName, eventHandlers) => {
296 document.addEventListener(eventName, e => {
297 const target = e.target;
298 let args = {
299 e,
300 target
301 };
302 eventHandlers.forEach(eventHandler => {
303 args = {
304 ...args,
305 ...eventHandler
306 };
307
308 //console.log( args );
309
310 // Check condition before call back
311 if (eventHandler.conditionBeforeCallBack) {
312 if (eventHandler.conditionBeforeCallBack(args) !== true) {
313 return;
314 }
315 }
316
317 // Special check for keydown event with checkIsEventEnter = true
318 if (eventName === 'keydown' && eventHandler.checkIsEventEnter) {
319 if (e.key !== 'Enter') {
320 return;
321 }
322 }
323 if (target.closest(eventHandler.selector)) {
324 if (eventHandler.class) {
325 // Call method of class, function callBack will understand exactly {this} is class object.
326 eventHandler.class[eventHandler.callBack](args);
327 } else {
328 // For send args is objected, {this} is eventHandler object, not class object.
329 eventHandler.callBack(args);
330 }
331 }
332 });
333 });
334 };
335
336 /**
337 * Debounce - delays function execution until after `wait` ms of inactivity.
338 *
339 * Each call resets the timer. Only the last call in a burst executes.
340 *
341 * USE CASES:
342 * - Search inputs, form validation, window resize
343 * - Multiple elements need independent timers
344 * - When you need to call with different arguments
345 *
346 * EXAMPLES:
347 * const debouncedSearch = debounce( (query) => fetchResults(query), 300 );
348 * searchInput.addEventListener('input', (e) => debouncedSearch(e.target.value));
349 *
350 * const debouncedResize = debounce( recalculateLayout, 250 );
351 * window.addEventListener('resize', debouncedResize);
352 *
353 * ⚠️ Create ONCE outside event handlers, not inside.
354 *
355 * @param {Function} func - Function to debounce (can be anonymous)
356 * @param {number} wait - Milliseconds to wait (default: 500)
357 * @return {Function} Debounced wrapper function
358 * @since 4.3.7
359 * @version 1.0.0
360 */
361 const debounce = (func, wait = 500) => {
362 let timer;
363 return args => {
364 clearTimeout(timer);
365 timer = setTimeout(() => func(args), wait);
366 };
367 };
368
369 /**
370 * Initialize lp-toggle-enable components.
371 *
372 * Finds all `.lp-toggle-enable` elements and wires up toggle behavior.
373 * Reads initial state from `data-enabled` attribute ("true"/"false").
374 * Calls `data-on-toggle` callback (if provided via options) on state change.
375 *
376 * HTML structure:
377 * <label class="lp-toggle-enable" data-enabled="true">
378 * <input type="checkbox" class="lp-toggle-enable__input" />
379 * <span class="lp-toggle-enable__track"></span>
380 * </label>
381 *
382 * @param {string} selector CSS selector for toggle elements (default: '.lp-toggle-enable')
383 * @param {Function} onToggle Optional callback( el, isEnabled ) called on state change
384 * @since 4.4.5
385 * @version 1.0.0
386 */
387 window.lpToggleEnableInit = 0;
388 const toggleEnable = (onToggle = null) => {
389 if (window.lpToggleEnableInit) {
390 return;
391 }
392 window.lpToggleEnableInit = 1;
393 const selector = '.lp-toggle-enable';
394 const updateUI = (toggle, isEnabled) => {
395 toggle.classList.toggle('is-enabled', isEnabled);
396 const input = toggle.querySelector('.lp-toggle-enable__input');
397 if (input) {
398 input.checked = isEnabled;
399 input.value = isEnabled ? '1' : '0';
400 }
401 };
402
403 // Delegate click handling via eventHandlers.
404 eventHandlers('click', [{
405 selector,
406 callBack: args => {
407 const {
408 e,
409 target
410 } = args;
411 const toggle = target.closest(selector);
412 if (!toggle || toggle.classList.contains('is-disabled')) {
413 return;
414 }
415 e.preventDefault();
416 const isEnabled = !toggle.classList.contains('is-enabled');
417 updateUI(toggle, isEnabled);
418 if ('function' === typeof onToggle) {
419 onToggle(toggle, isEnabled);
420 }
421 }
422 }]);
423 };
424
425 /**
426 * Initialize custom fullscreen view buttons.
427 *
428 * Delegates clicks on `.lp-btn-full-screen-view` buttons to
429 * `lpToggleFullscreenView`. Reads the `data-target` attribute to find the
430 * target element. Falls back to the button's parent element when
431 * `data-target` is not provided.
432 *
433 * @since 4.4.5
434 * @version 1.0.0
435 */
436 window.lpFullScreenViewInit = 0;
437 const fullScreenView = () => {
438 if (window.lpFullScreenViewInit) {
439 return;
440 }
441 window.lpFullScreenViewInit = 1;
442 let lastScrollY = 0;
443 const lpToggleFullscreenView = (elTarget, elBtnFullScreen = null) => {
444 const isFullscreen = elTarget.classList.contains(lpClassName.elFullScreen);
445 if (isFullscreen) {
446 elTarget.classList.remove(lpClassName.elFullScreen);
447 document.documentElement.classList.remove('lp-full-screen-active');
448 window.scrollTo(0, lastScrollY);
449 } else {
450 lastScrollY = window.scrollY;
451 elTarget.classList.add(lpClassName.elFullScreen);
452 document.documentElement.classList.add('lp-full-screen-active');
453 }
454 if (!isFullscreen) {
455 if (!elTarget.querySelector(`.${lpClassName.elBtnFullScreenClose}`)) {
456 const closeButton = document.createElement('button');
457 closeButton.type = 'button';
458 closeButton.className = lpClassName.elBtnFullScreenClose;
459 closeButton.setAttribute('aria-label', 'Close');
460 closeButton.innerHTML = lpData.i18n.closeButtonFullScreen || 'Close &times;';
461 closeButton.addEventListener('click', e => {
462 e.preventDefault();
463 lpToggleFullscreenView(elTarget);
464 });
465 elTarget.appendChild(closeButton);
466 }
467 } else {
468 const closeButton = elTarget.querySelector(`.${lpClassName.elBtnFullScreenClose}`);
469 if (closeButton) {
470 closeButton.remove();
471 }
472 }
473 };
474 eventHandlers('click', [{
475 selector: lpClassName.elBtnFullScreen,
476 callBack: args => {
477 const {
478 e,
479 target
480 } = args;
481 const elBtnFullScreen = target.closest(lpClassName.elBtnFullScreen);
482 if (!elBtnFullScreen) {
483 console.log('No full screen button found');
484 return;
485 }
486 e.preventDefault();
487 let elTarget = null;
488 const targetSelector = elBtnFullScreen.dataset.targetFullscreen;
489 console.log(targetSelector);
490 if (targetSelector) {
491 elTarget = document.querySelector(targetSelector);
492 }
493 if (!elTarget) {
494 console.log('No target element found');
495 return;
496 }
497 lpToggleFullscreenView(elTarget, elBtnFullScreen);
498 }
499 }]);
500 };
501
502 /***/ }
503
504 /******/ });
505 /************************************************************************/
506 /******/ // The module cache
507 /******/ var __webpack_module_cache__ = {};
508 /******/
509 /******/ // The require function
510 /******/ function __webpack_require__(moduleId) {
511 /******/ // Check if module is in cache
512 /******/ var cachedModule = __webpack_module_cache__[moduleId];
513 /******/ if (cachedModule !== undefined) {
514 /******/ return cachedModule.exports;
515 /******/ }
516 /******/ // Create a new module (and put it into the cache)
517 /******/ var module = __webpack_module_cache__[moduleId] = {
518 /******/ // no module.id needed
519 /******/ // no module.loaded needed
520 /******/ exports: {}
521 /******/ };
522 /******/
523 /******/ // Execute the module function
524 /******/ if (!(moduleId in __webpack_modules__)) {
525 /******/ delete __webpack_module_cache__[moduleId];
526 /******/ var e = new Error("Cannot find module '" + moduleId + "'");
527 /******/ e.code = 'MODULE_NOT_FOUND';
528 /******/ throw e;
529 /******/ }
530 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
531 /******/
532 /******/ // Return the exports of the module
533 /******/ return module.exports;
534 /******/ }
535 /******/
536 /************************************************************************/
537 /******/ /* webpack/runtime/define property getters */
538 /******/ (() => {
539 /******/ // define getter functions for harmony exports
540 /******/ __webpack_require__.d = (exports, definition) => {
541 /******/ for(var key in definition) {
542 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
543 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
544 /******/ }
545 /******/ }
546 /******/ };
547 /******/ })();
548 /******/
549 /******/ /* webpack/runtime/hasOwnProperty shorthand */
550 /******/ (() => {
551 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
552 /******/ })();
553 /******/
554 /******/ /* webpack/runtime/make namespace object */
555 /******/ (() => {
556 /******/ // define __esModule on exports
557 /******/ __webpack_require__.r = (exports) => {
558 /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
559 /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
560 /******/ }
561 /******/ Object.defineProperty(exports, '__esModule', { value: true });
562 /******/ };
563 /******/ })();
564 /******/
565 /************************************************************************/
566 var __webpack_exports__ = {};
567 // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
568 (() => {
569 /*!*******************************************!*\
570 !*** ./assets/src/js/admin/learnpress.js ***!
571 \*******************************************/
572 __webpack_require__.r(__webpack_exports__);
573 /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils */ "./assets/src/js/utils.js");
574
575 const $ = jQuery;
576 const $doc = $(document);
577 const makePaymentsSortable = function makePaymentsSortable() {
578 // Make payments sortable
579 $('.learn-press-payments.sortable tbody').sortable({
580 handle: '.dashicons-menu',
581 helper(e, ui) {
582 ui.children().each(function () {
583 $(this).width($(this).width());
584 });
585 return ui;
586 },
587 axis: 'y',
588 start(event, ui) {},
589 stop(event, ui) {},
590 update(event, ui) {
591 const order = $(this).children().map(function () {
592 return $(this).find('input[name="payment-order"]').val();
593 }).get();
594 $.post({
595 url: '',
596 data: {
597 'lp-ajax': 'update-payment-order',
598 order,
599 nonce: $('input[name=lp-settings-nonce]').val()
600 },
601 success(response) {}
602 });
603 }
604 });
605 };
606
607 /** Start Nhamdv code */
608
609 const lpMetaboxCustomFields = () => {
610 $('.lp-metabox__custom-fields').on('click', '.lp-metabox-custom-field-button', function () {
611 const row = $(this).data('row').replace(/lp_metabox_custom_fields_key/gi, Math.floor(Math.random() * 1000) + 1);
612 $(this).closest('table').find('tbody').append(row);
613 updateSort($(this).closest('.lp-metabox__custom-fields'));
614 return false;
615 });
616 $('.lp-metabox__custom-fields').on('click', 'a.delete', function () {
617 $(this).closest('tr').remove();
618 updateSort($(this).closest('.lp-metabox__custom-fields'));
619 return false;
620 });
621 $('.lp-metabox__custom-fields tbody').sortable({
622 items: 'tr',
623 cursor: 'move',
624 axis: 'y',
625 handle: 'td.sort',
626 scrollSensitivity: 40,
627 forcePlaceholderSize: true,
628 helper: 'clone',
629 opacity: 0.65,
630 update(event, ui) {
631 updateSort($(this).closest('.lp-metabox__custom-fields'));
632 }
633 });
634 const updateSort = element => {
635 const items = element.find('tbody tr');
636 items.each(function (i, item) {
637 $(this).find('.sort .count').val(i);
638 });
639 };
640 };
641 const lpMetaboxRepeaterField = () => {
642 const updateSort = element => {
643 const items = element.find('.lp_repeater_meta_box__field');
644 items.each(function (i, item) {
645 $(this).find('.lp_repeater_meta_box__field__count').val(i);
646 $(this).find('.lp_repeater_meta_box__title__title > span').text(i + 1);
647 });
648 };
649 $('.lp_repeater_meta_box__add').on('click', function () {
650 const row = $(this).data('add').replace(/lp_metabox_repeater_key/gi, Math.floor(Math.random() * 1000) + 1);
651 $(this).closest('.lp_repeater_meta_box__wrapper').find('.lp_repeater_meta_box__fields').append(row);
652 updateSort($(this).closest('.lp_repeater_meta_box__wrapper'));
653 $(this).closest('.lp_repeater_meta_box__wrapper').find('.lp_repeater_meta_box__fields').last().find('input').trigger('focus');
654 return false;
655 });
656 $('.lp_repeater_meta_box__wrapper').on('click', 'a.lp_repeater_meta_box__title__delete', function () {
657 $(this).closest('.lp_repeater_meta_box__field').remove();
658 updateSort($(this).closest('.lp_repeater_meta_box__wrapper'));
659 return false;
660 });
661 $('.lp_repeater_meta_box__fields').on('click', '.lp_repeater_meta_box__title__toggle, .lp_repeater_meta_box__title__title', function () {
662 const field = $(this).closest('.lp_repeater_meta_box__field');
663 if (field.hasClass('lp_repeater_meta_box__field_active')) {
664 field.removeClass('lp_repeater_meta_box__field_active');
665 } else {
666 field.addClass('lp_repeater_meta_box__field_active');
667 }
668 return false;
669 });
670 $('.lp_repeater_meta_box__fields').sortable({
671 items: '.lp_repeater_meta_box__field',
672 cursor: 'grab',
673 axis: 'y',
674 handle: '.lp_repeater_meta_box__title__sort',
675 scrollSensitivity: 40,
676 forcePlaceholderSize: true,
677 helper: 'clone',
678 opacity: 0.65,
679 update(event, ui) {
680 updateSort($(this).closest('.lp_repeater_meta_box__wrapper'));
681 }
682 });
683 };
684 const lpMetaboxExtraInfo = () => {
685 $('.lp_course_extra_meta_box__add').on('click', function () {
686 $(this).closest('.lp_course_extra_meta_box__content').find('.lp_course_extra_meta_box__fields').append($(this).data('add'));
687 $(this).closest('.lp_course_extra_meta_box__content').find('.lp_course_extra_meta_box__field').last().find('input').trigger('focus');
688 return false;
689 });
690
691 /*document.querySelectorAll( '.lp_course_extra_meta_box__fields' ).forEach( ( ele ) => {
692 ele.addEventListener( 'keydown', ( e ) => {
693 const inputs = ele.querySelectorAll( '.lp_course_extra_meta_box__input' );
694 if ( e.keyCode === 13 ) {
695 e.preventDefault();
696 inputs.forEach( ( input ) => {
697 input.blur();
698 } );
699 return false;
700 }
701 } );
702 } );*/
703
704 $('.lp_course_extra_meta_box__fields').on('click', 'a.delete', function () {
705 $(this).closest('.lp_course_extra_meta_box__field').remove();
706 return false;
707 });
708 $('.lp_course_extra_meta_box__fields').sortable({
709 items: '.lp_course_extra_meta_box__field',
710 cursor: 'grab',
711 axis: 'y',
712 handle: '.sort',
713 scrollSensitivity: 40,
714 forcePlaceholderSize: true,
715 helper: 'clone',
716 opacity: 0.65
717 });
718
719 // FAQs metabox.
720 $('.lp_course_faq_meta_box__add').on('click', function () {
721 $(this).closest('.lp_course_faq_meta_box__content').find('.lp_course_faq_meta_box__fields').append($(this).data('add'));
722 return false;
723 });
724
725 /*document.querySelectorAll( '.lp_course_faq_meta_box__fields' ).forEach( ( ele ) => {
726 ele.addEventListener( 'keydown', ( e ) => {
727 const inputs = ele.querySelectorAll( '.lp_course_faq_meta_box__field input' );
728 const textareas = ele.querySelectorAll( '.lp_course_faq_meta_box__field textarea' );
729 if ( e.keyCode === 13 ) {
730 e.preventDefault();
731 [ ...inputs, ...textareas ].forEach( ( input ) => {
732 input.blur();
733 } );
734 return false;
735 }
736 } );
737 } );*/
738
739 $('.lp_course_faq_meta_box__fields').on('click', 'a.delete', function () {
740 $(this).closest('.lp_course_faq_meta_box__field').remove();
741 return false;
742 });
743 $('.lp_course_faq_meta_box__fields').sortable({
744 items: '.lp_course_faq_meta_box__field',
745 cursor: 'grab',
746 axis: 'y',
747 handle: '.sort',
748 scrollSensitivity: 40,
749 forcePlaceholderSize: true,
750 helper: 'clone',
751 opacity: 0.65
752 });
753 };
754
755 // Nhamdv.
756 const lpGetFinalQuiz = () => {
757 const btns = document.querySelectorAll('.lp-metabox-get-final-quiz');
758 [...btns].map(btn => {
759 btn.addEventListener('click', e => {
760 e.preventDefault();
761 const text = btn.textContent,
762 loading = btn.dataset.loading,
763 message = document.querySelector('.lp-metabox-evaluate-final_quiz');
764 if (message) {
765 message.remove();
766 }
767 btn.textContent = loading;
768 getResponse(btn).then(data => {
769 const {
770 message,
771 data: responseData
772 } = data;
773 btn.textContent = text;
774 const newNode = document.createElement('div');
775 newNode.className = 'lp-metabox-evaluate-final_quiz';
776 newNode.innerHTML = responseData || message;
777 btn.parentNode.insertBefore(newNode, btn.nextSibling);
778 });
779 });
780 });
781 const getResponse = async btn => {
782 const response = await wp.apiFetch({
783 path: 'lp/v1/admin/course/get_final_quiz',
784 method: 'POST',
785 data: {
786 courseId: btn.dataset.postid || ''
787 }
788 });
789 return response;
790 };
791 };
792 const lpMetaboxColorPicker = () => {
793 $('.lp-metabox__colorpick').iris({
794 change(event, ui) {
795 $(this).parent().find('.colorpickpreview').css({
796 backgroundColor: ui.color.toString()
797 });
798 },
799 hide: true,
800 border: true
801 }).on('click focus', function (event) {
802 event.stopPropagation();
803 $('.iris-picker').hide();
804 $(this).closest('td').find('.iris-picker').show();
805 $(this).data('original-value', $(this).val());
806 }).on('change', function () {
807 if ($(this).is('.iris-error')) {
808 const originalValue = $(this).data('original-value');
809 if (originalValue.match(/^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/)) {
810 $(this).val($(this).data('original-value')).trigger('change');
811 } else {
812 $(this).val('').trigger('change');
813 }
814 }
815 });
816 $('body').on('click', function () {
817 $('.iris-picker').hide();
818 });
819 };
820 const lpMetaboxImage = () => {
821 $('.lp-metabox-field__image').each((i, ele) => {
822 let lpImageFrame;
823 const addImage = $(ele).find('.lp-metabox-field__image--add');
824 const delImage = $(ele).find('.lp-metabox-field__image--delete');
825 const image = $(ele).find('.lp-metabox-field__image--image');
826 const inputVal = $(ele).find('.lp-metabox-field__image--id');
827 if (!inputVal.val()) {
828 addImage.show();
829 delImage.hide();
830 } else {
831 addImage.hide();
832 delImage.show();
833 }
834 addImage.on('click', event => {
835 event.preventDefault();
836 if (lpImageFrame) {
837 lpImageFrame.open();
838 return;
839 }
840 lpImageFrame = wp.media({
841 title: addImage.data('choose'),
842 button: {
843 text: addImage.data('update')
844 },
845 multiple: false
846 });
847 lpImageFrame.on('select', function () {
848 const attachment = lpImageFrame.state().get('selection').first().toJSON();
849 const attachmentImage = attachment.sizes && attachment.sizes.thumbnail ? attachment.sizes.thumbnail.url : attachment.url;
850 image.append('<div class="lp-metabox-field__image--inner"><img src="' + attachmentImage + '" alt="" style="max-width:100%;"/></div>');
851 inputVal.val(attachment.id);
852 addImage.hide();
853 delImage.show();
854 });
855 lpImageFrame.open();
856 });
857 delImage.on('click', event => {
858 event.preventDefault();
859 image.html('');
860 addImage.show();
861 delImage.hide();
862 inputVal.val('');
863 });
864 });
865 };
866 const lpMetaboxImageAdvanced = () => {
867 $('.lp-metabox-field__image-advanced').each((i, element) => {
868 let lpImageFrame;
869 const imageGalleryIds = $(element).find('#lp-gallery-images-ids');
870 const listImages = $(element).find('.lp-metabox-field__image-advanced-images');
871 const btnUpload = $(element).find('.lp-metabox-field__image-advanced-upload > a');
872 $(btnUpload).on('click', event => {
873 event.preventDefault();
874 if (lpImageFrame) {
875 lpImageFrame.open();
876 return;
877 }
878 lpImageFrame = wp.media({
879 title: btnUpload.data('choose'),
880 button: {
881 text: btnUpload.data('update')
882 },
883 states: [new wp.media.controller.Library({
884 title: btnUpload.data('choose'),
885 filterable: 'all',
886 multiple: true
887 })]
888 });
889 lpImageFrame.on('select', function () {
890 const selection = lpImageFrame.state().get('selection');
891 let attachmentIds = imageGalleryIds.val();
892 selection.forEach(function (attachment) {
893 attachment = attachment.toJSON();
894 if (attachment.id) {
895 attachmentIds = attachmentIds ? attachmentIds + ',' + attachment.id : attachment.id;
896 const attachmentImage = attachment.sizes && attachment.sizes.thumbnail ? attachment.sizes.thumbnail.url : attachment.url;
897 listImages.append('<li class="image" data-attachment_id="' + attachment.id + '"><img src="' + attachmentImage + '" /><ul class="actions"><li><a href="#" class="delete" title="' + btnUpload.data('delete') + '">' + btnUpload.data('text') + '</a></li></ul></li>');
898 }
899 });
900 imageGalleryIds.val(attachmentIds);
901 });
902 lpImageFrame.open();
903 });
904 listImages.sortable({
905 items: 'li.image',
906 cursor: 'move',
907 scrollSensitivity: 40,
908 forcePlaceholderSize: true,
909 forceHelperSize: false,
910 helper: 'clone',
911 opacity: 0.65,
912 placeholder: 'lp-metabox-sortable-placeholder',
913 start(event, ui) {
914 ui.item.css('background-color', '#f6f6f6');
915 },
916 stop(event, ui) {
917 ui.item.removeAttr('style');
918 },
919 update() {
920 let attachmentIds = '';
921 listImages.find('li.image').css('cursor', 'default').each(function () {
922 const attachmentId = $(this).attr('data-attachment_id');
923 attachmentIds = attachmentIds + attachmentId + ',';
924 });
925 imageGalleryIds.val(attachmentIds);
926 }
927 });
928 $(listImages).find('li.image').each((i, ele) => {
929 const del = $(ele).find('a.delete');
930 del.on('click', () => {
931 $(ele).remove();
932 let attachmentIds = '';
933 $(listImages).find('li.image').css('cursor', 'default').each(function () {
934 const attachmentId = $(this).attr('data-attachment_id');
935 attachmentIds = attachmentIds + attachmentId + ',';
936 });
937 imageGalleryIds.val(attachmentIds);
938 return false;
939 });
940 });
941 });
942 };
943 const lpMetaboxCourseTabs = () => {
944 $(document.body).on('lp-metabox-course-tab-panels', function () {
945 $('ul.lp-meta-box__course-tab__tabs').show();
946 $('ul.lp-meta-box__course-tab__tabs a').on('click', function (e) {
947 e.preventDefault();
948 const panelWrap = $(this).closest('div.lp-meta-box__course-tab');
949 $('ul.lp-meta-box__course-tab__tabs li', panelWrap).removeClass('active');
950 $(this).parent().addClass('active');
951 $('div.lp-meta-box-course-panels', panelWrap).hide();
952 $($(this).attr('href')).show();
953 });
954 $('div.lp-meta-box__course-tab').each(function () {
955 $(this).find('ul.lp-meta-box__course-tab__tabs li').eq(0).find('a').trigger('click');
956 });
957 }).trigger('lp-metabox-course-tab-panels');
958 };
959
960 // use to show and hide field condition logic metabox.
961 /*const lpMetaboxCondition = () => {
962 const fields = document.querySelectorAll( '.lp-meta-box .form-field' );
963
964 fields.forEach( ( field ) => {
965 if ( field.hasAttribute( 'data-show' ) && field.dataset.show ) {
966 lpMetaboxConditionType( field, field.dataset.show, 'show' );
967 } else if ( field.hasAttribute( 'data-hide' ) && field.dataset.hide ) {
968 lpMetaboxConditionType( field, field.dataset.hide, 'hide' );
969 }
970 } );
971 };*/
972
973 /*const lpMetaboxConditionType = ( field, conditions, typeCondition = 'show' ) => {
974 const condition = JSON.parse( conditions ),
975 eles = document.querySelectorAll( `input[id^="${ condition[ 0 ] }"]` ),
976 logic = condition[ 1 ] === '=' ? '=' : '!=',
977 dataLogic = condition[ 2 ];
978
979 const switchCase = ( type, ele, target ) => {
980 switch ( type ) {
981 case 'checkbox':
982 let val = dataLogic;
983
984 if ( dataLogic === 'yes' || dataLogic === '1' || dataLogic === 1 || dataLogic === 'true' ) {
985 val = true;
986 } else if ( dataLogic === 'no' || dataLogic === '0' || dataLogic === 0 || dataLogic === 'false' ) {
987 val = false;
988 }
989
990 if ( logic == '!=' && val !== Boolean( target ? target.checked : ele.checked ) ) {
991 field.style.display = typeCondition === 'show' ? '' : 'none';
992 } else if ( logic == '=' && val == Boolean( target ? target.checked : ele.checked ) ) {
993 field.style.display = typeCondition === 'show' ? '' : 'none';
994 } else {
995 field.style.display = typeCondition === 'show' ? 'none' : '';
996 }
997 break;
998 }
999 };
1000
1001 eles.forEach( ( ele ) => {
1002 const type = ele.getAttribute( 'type' );
1003
1004 switchCase( type, ele );
1005
1006 ele.addEventListener( 'change', ( e ) => {
1007 const target = e.target;
1008
1009 switchCase( type, ele, target );
1010 } );
1011 } );
1012 };*/
1013
1014 /** End Nhamdv code */
1015
1016 const initTooltips = function initTooltips() {
1017 $('.learn-press-tooltip').each(function () {
1018 const $el = $(this),
1019 args = $.extend({
1020 title: 'data-tooltip',
1021 offset: 10,
1022 gravity: 's'
1023 }, $el.data());
1024 $el.tipsy(args);
1025 });
1026 };
1027 const initSelect2 = function initSelect2() {
1028 if ($.fn.select2) {
1029 const elSelect2 = $('.lp-select-2 select');
1030 elSelect2.select2({
1031 placeholder: 'Select a value'
1032 });
1033 elSelect2.on('change.select2', function (e) {
1034 const el = $(e.target);
1035 const val = el.val();
1036 if (!val.length) {
1037 el.val(null);
1038 }
1039 });
1040 $('.lp_autocomplete_metabox_field').each(function () {
1041 const dataAtts = $(this).data('atts');
1042 let action = dataAtts.action;
1043 if (!action) {
1044 switch (dataAtts.data) {
1045 case 'users':
1046 action = dataAtts.rest_url + 'wp/v2/users';
1047 break;
1048 default:
1049 action = dataAtts.rest_url + 'wp/v2/' + dataAtts.data;
1050 break;
1051 }
1052 }
1053 $(this).find('select').select2({
1054 placeholder: dataAtts.placeholder ? dataAtts.placeholder : 'Select',
1055 ajax: {
1056 url: action,
1057 dataType: 'json',
1058 delay: 250,
1059 beforeSend(xhr) {
1060 xhr.setRequestHeader('X-WP-Nonce', dataAtts.nonce);
1061 },
1062 data(params) {
1063 return {
1064 search: params.term
1065 };
1066 },
1067 processResults(data) {
1068 return {
1069 results: data.map(item => {
1070 return {
1071 id: item.id,
1072 text: item.title && item.title.rendered ? item.title.rendered : item.name
1073 };
1074 })
1075 };
1076 },
1077 cache: true
1078 },
1079 minimumInputLength: 2
1080 });
1081 });
1082 }
1083 };
1084 const initSingleCoursePermalink = function initSingleCoursePermalink() {
1085 $doc.on('change', '.learn-press-single-course-permalink input[type="radio"]', function () {
1086 const $check = $(this),
1087 $row = $check.closest('.learn-press-single-course-permalink');
1088 if ($row.hasClass('custom-base')) {
1089 $row.find('input[type="text"]').prop('readonly', false);
1090 } else {
1091 $row.siblings('.custom-base').find('input[type="text"]').prop('readonly', true);
1092 }
1093 }).on('change', 'input.learn-press-course-base', function () {
1094 $('#course_permalink_structure').val($(this).val());
1095 }).on('focus', '#course_permalink_structure', function () {
1096 $('#learn_press_custom_permalink').click();
1097 }).on('change', '#learn_press_courses_page_id', function () {
1098 $('tr.learn-press-courses-page-id').toggleClass('hide-if-js', !parseInt(this.value));
1099 });
1100 };
1101 const togglePaymentStatus = function togglePaymentStatus(e) {
1102 e.preventDefault();
1103 const $row = $(this).closest('tr'),
1104 $button = $(this),
1105 status = $row.find('.status').hasClass('enabled') ? 'no' : 'yes';
1106 $.ajax({
1107 url: '',
1108 data: {
1109 'lp-ajax': 'update-payment-status',
1110 status,
1111 id: $row.data('payment'),
1112 nonce: $('input[name=lp-settings-nonce]').val()
1113 },
1114 success(response) {
1115 response = (0,_utils__WEBPACK_IMPORTED_MODULE_0__.lpAjaxParseJsonOld)(response);
1116 for (const i in response) {
1117 $('#payment-' + i + ' .status').toggleClass('enabled', response[i]);
1118 }
1119 }
1120 });
1121 };
1122 const updateEmailStatus = function updateEmailStatus() {
1123 (function () {
1124 $.post({
1125 url: window.location.href,
1126 data: {
1127 'lp-ajax': 'update_email_status',
1128 status: $(this).parent().hasClass('enabled') ? 'no' : 'yes',
1129 id: $(this).data('id'),
1130 nonce: $('input[name=lp-settings-nonce]').val()
1131 },
1132 dataType: 'text',
1133 success: $.proxy(function (res) {
1134 res = (0,_utils__WEBPACK_IMPORTED_MODULE_0__.lpAjaxParseJsonOld)(res);
1135 for (const i in res) {
1136 $('#email-' + i + ' .status').toggleClass('enabled', res[i]);
1137 }
1138 }, this)
1139 });
1140 }).apply(this);
1141 };
1142 const lpMetaboxsalePriceDate = () => {
1143 // Don't run in LearnPress Frontend Editor Add-on.
1144 if (!$('#course-settings').length) {
1145 return;
1146 }
1147 $('.lp_sale_dates_fields').each(function () {
1148 const wrap = $(this).closest('#price_course_data');
1149 let saleScheduleSet = false;
1150 $(this).find('input').each(function () {
1151 if ('' !== $(this).val()) {
1152 saleScheduleSet = true;
1153 }
1154 });
1155 if (saleScheduleSet) {
1156 wrap.find('.lp_sale_price_schedule').hide();
1157 wrap.find('.lp_sale_dates_fields').show();
1158 } else {
1159 wrap.find('.lp_sale_price_schedule').show();
1160 wrap.find('.lp_sale_dates_fields').hide();
1161 }
1162 });
1163 $('.lp-meta-box-course-panels').on('click', '.lp_sale_price_schedule', function () {
1164 const wrap = $(this).closest('#price_course_data');
1165 $(this).hide();
1166 wrap.find('.lp_cancel_sale_schedule').show();
1167 wrap.find('.lp_sale_dates_fields').show();
1168 return false;
1169 });
1170 $('.lp-meta-box-course-panels').on('click', '.lp_cancel_sale_schedule', function () {
1171 const wrap = $(this).closest('div.lp-meta-box-course-panels');
1172 $(this).hide();
1173 wrap.find('.lp_sale_price_schedule').show();
1174 wrap.find('.lp_sale_dates_fields').hide();
1175 wrap.find('.lp_sale_dates_fields').find('input').val('');
1176 return false;
1177 });
1178 $(document).on('input', '#price_course_data', function (e) {
1179 const $this = $(this),
1180 regularPrice = $('.lp_meta_box_regular_price'),
1181 salePrice = $('.lp_meta_box_sale_price'),
1182 $target = $(e.target).attr('id');
1183 $this.find('.learn-press-tip-floating').remove();
1184 if (parseInt(salePrice.val()) > parseInt(regularPrice.val())) {
1185 if ($target === '_lp_price') {
1186 regularPrice.parent('.form-field').append('<div class="learn-press-tip-floating">' + lpAdminCourseEditorSettings.i18n.notice_price + '</div>');
1187 } else if ($target === '_lp_sale_price') {
1188 salePrice.parent('.form-field').append('<div class="learn-press-tip-floating">' + lpAdminCourseEditorSettings.i18n.notice_sale_price + '</div>');
1189 }
1190 }
1191 });
1192
1193 /*const datePickerSelect = function( datepicker ) {
1194 const option = $( datepicker ).is( '#_lp_sale_start' ) ? 'minDate' : 'maxDate',
1195 otherDateField = 'minDate' === option ? $( '#_lp_sale_end' ) : $( '#_lp_sale_start' ),
1196 date = $( datepicker ).datetimepicker( 'getDate' );
1197 $( otherDateField ).datetimepicker( 'option', option, date );
1198 $( datepicker ).trigger( 'change' );
1199 };
1200 $( '.lp_sale_dates_fields' ).each( function() {
1201 $( this ).find( 'input' ).datetimepicker( {
1202 timeFormat: 'HH:mm',
1203 separator: ' ',
1204 dateFormat: 'yy-mm-dd',
1205 showButtonPanel: true,
1206 onSelect() {
1207 datePickerSelect( $( this ) );
1208 },
1209 } );
1210 $( this ).find( 'input' ).each( function() {
1211 datePickerSelect( $( this ) );
1212 } );
1213 } );*/
1214 };
1215 const lpHidePassingGrade = () => {
1216 const listHides = ['evaluate_final_quiz', 'evaluate_final_assignment'];
1217 const inputLists = document.querySelectorAll('input[type=radio][name=_lp_course_result]');
1218 [...inputLists].map((ele, i) => {
1219 if (ele.checked && listHides.includes(ele.value)) {
1220 $('._lp_passing_condition_field').hide();
1221 }
1222 return null;
1223 });
1224 $('input[type=radio][name=_lp_course_result]').on('change', function (e) {
1225 if (listHides.includes(e.target.value)) {
1226 $('._lp_passing_condition_field').hide();
1227 } else {
1228 $('._lp_passing_condition_field').show();
1229 }
1230 });
1231 };
1232 const callbackFilterTemplates = function callbackFilterTemplates() {
1233 const $link = $(this);
1234 if ($link.hasClass('current')) {
1235 return false;
1236 }
1237 const $templatesList = $('#learn-press-template-files'),
1238 $templates = $templatesList.find('tr[data-template]'),
1239 template = $link.data('template'),
1240 filter = $link.data('filter');
1241 $link.addClass('current').siblings('a').removeClass('current');
1242 if (!template) {
1243 if (!filter) {
1244 $templates.removeClass('hide-if-js');
1245 } else {
1246 $templates.map(function () {
1247 $(this).toggleClass('hide-if-js', $(this).data('filter-' + filter) !== 'yes');
1248 });
1249 }
1250 } else {
1251 $templates.map(function () {
1252 $(this).toggleClass('hide-if-js', $(this).data('template') !== template);
1253 });
1254 }
1255 $('#learn-press-no-templates').toggleClass('hide-if-js', !!$templatesList.find('tr.template-row:not(.hide-if-js):first').length);
1256 return false;
1257 };
1258 const toggleEmails = function toggleEmails(e) {
1259 e.preventDefault();
1260 const $button = $(this),
1261 status = $button.data('status');
1262 $.ajax({
1263 url: '',
1264 data: {
1265 'lp-ajax': 'update_email_status',
1266 nonce: $('input[name=lp-settings-nonce]').val(),
1267 status
1268 },
1269 success(response) {
1270 response = (0,_utils__WEBPACK_IMPORTED_MODULE_0__.lpAjaxParseJsonOld)(response);
1271 for (const i in response) {
1272 $('#email-' + i + ' .status').toggleClass('enabled', response[i]);
1273 }
1274 }
1275 });
1276 };
1277 const onReady = function onReady() {
1278 makePaymentsSortable();
1279 initSelect2();
1280 initTooltips();
1281 initSingleCoursePermalink();
1282
1283 // lp Metabox in LP4.
1284 lpMetaboxCourseTabs();
1285 lpMetaboxCustomFields();
1286 lpMetaboxColorPicker();
1287 lpMetaboxImageAdvanced();
1288 lpMetaboxImage();
1289 lpMetaboxsalePriceDate();
1290 lpMetaboxExtraInfo();
1291 lpHidePassingGrade();
1292 lpGetFinalQuiz();
1293 //lpMetaboxCondition();
1294 lpMetaboxRepeaterField();
1295 $(document).on('click', '.learn-press-payments .status .dashicons', togglePaymentStatus).on('click', '.change-email-status', updateEmailStatus).on('click', '.learn-press-filter-template', callbackFilterTemplates).on('click', '#learn-press-enable-emails, #learn-press-disable-emails', toggleEmails);
1296 };
1297 $(document).ready(onReady);
1298
1299 // Events
1300 document.addEventListener('keydown', function (e) {
1301 const target = e.target;
1302 if (e.key === 'Enter' || e.keyCode === 13) {
1303 // When enter on input on Extra information Options, blur it.
1304 if (target.classList.contains('lp_course_extra_meta_box__input')) {
1305 e.preventDefault();
1306 target.blur();
1307 } else if (target.tagName === 'INPUT') {
1308 if (target.closest('.lp_course_faq_meta_box__field')) {
1309 e.preventDefault();
1310 target.blur();
1311 }
1312 }
1313 }
1314 });
1315 })();
1316
1317 /******/ })()
1318 ;
1319 //# sourceMappingURL=learnpress.js.map