PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.9
4.4.9 4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 All 140 releases
← All changes | assets/src/js/admin/edit-course/edit-curriculum/edit-section.js +803 -803 4.3.8 → 4.4.9 View file →
@@ -1,803 +1,803 @@
1 -/**
2 - * Edit Section Script on Curriculum
3 - *
4 - * @since 4.2.8.6
5 - * @version 1.0.3
6 - */
7 -import SweetAlert from 'sweetalert2';
8 -import Sortable from 'sortablejs';
9 -import * as lpUtils from 'lpAssetsJsPath/utils.js';
10 -import * as lpToastify from 'lpAssetsJsPath/lpToastify.js';
11 -import { EditSectionItem } from './edit-section-item.js';
12 -import { EditCourseCurriculum } from '../edit-curriculum.js';
13 -
14 -export class EditSection {
15 - constructor() {
16 - this.courseId = null;
17 - this.elEditCurriculum = null;
18 - this.elCurriculumSections = null;
19 - this.editSectionItem = new EditSectionItem();
20 - }
21 -
22 - static selectors = {
23 - elSection: '.section',
24 - elDivAddNewSection: '.add-new-section',
25 - elSectionClone: '.section.clone',
26 - elSectionTitleNewInput: '.lp-section-title-new-input',
27 - elSectionTitleInput: '.lp-section-title-input',
28 - etBtnEditTitle: '.lp-btn-edit-section-title',
29 - elSectionDesInput: '.lp-section-description-input',
30 - elBtnAddSection: '.lp-btn-add-section',
31 - elBtnUpdateTitle: '.lp-btn-update-section-title',
32 - elBtnUpdateDes: '.lp-btn-update-section-description',
33 - elBtnCancelUpdateTitle: '.lp-btn-cancel-update-section-title',
34 - elBtnCancelUpdateDes: '.lp-btn-cancel-update-section-description',
35 - elBtnDeleteSection: '.lp-btn-delete-section',
36 - elSectionDesc: '.section-description',
37 - elSectionToggle: '.section-toggle',
38 - elCountSections: '.count-sections',
39 - };
40 -
41 - init() {
42 - this.elEditCurriculum = document.querySelector(
43 - `${ EditCourseCurriculum.selectors.idElEditCurriculum }`
44 - );
45 - this.elCurriculumSections = this.elEditCurriculum.querySelector(
46 - `${ EditCourseCurriculum.selectors.elCurriculumSections }`
47 - );
48 - const elLPTarget = this.elEditCurriculum.closest(
49 - `${ EditCourseCurriculum.selectors.LPTarget }`
50 - );
51 - const dataSend = window.lpAJAXG.getDataSetCurrent( elLPTarget );
52 - this.courseId = dataSend.args.course_id;
53 -
54 - this.editSectionItem.init();
55 -
56 - this.events();
57 - this.sortAbleSection();
58 - }
59 -
60 - events() {
61 - // Check and attach events only once
62 - if ( EditSection._loadedEvents ) {
63 - return;
64 - }
65 -
66 - EditSection._loadedEvents = this;
67 -
68 - // Click events
69 - lpUtils.eventHandlers( 'click', [
70 - {
71 - selector: EditSection.selectors.elBtnAddSection,
72 - class: this,
73 - callBack: this.addSection.name,
74 - },
75 - {
76 - selector: `${ EditSection.selectors.elBtnUpdateDes }`,
77 - class: this,
78 - callBack: this.updateSectionDescription.name,
79 - },
80 - {
81 - selector: `${ EditSection.selectors.etBtnEditTitle }`,
82 - class: this,
83 - callBack: this.setFocusTitleInput.name,
84 - },
85 - {
86 - selector: `${ EditSection.selectors.elSectionToggle }`,
87 - class: this,
88 - callBack: this.toggleSection.name,
89 - },
90 - {
91 - selector: `${ EditSection.selectors.elBtnCancelUpdateDes }`,
92 - class: this,
93 - callBack: this.cancelSectionDescription.name,
94 - },
95 - {
96 - selector: `${ EditSection.selectors.elBtnDeleteSection }`,
97 - class: this,
98 - callBack: this.deleteSection.name,
99 - },
100 - {
101 - selector: `${ EditSection.selectors.elBtnUpdateTitle }`,
102 - class: this,
103 - callBack: this.updateSectionTitle.name,
104 - },
105 - {
106 - selector: `${ EditSection.selectors.elBtnCancelUpdateTitle }`,
107 - class: this,
108 - callBack: this.cancelSectionTitle.name,
109 - },
110 - {
111 - selector: EditCourseCurriculum.selectors.elToggleAllSections,
112 - class: this,
113 - callBack: this.toggleSectionAll.name,
114 - },
115 - ] );
116 -
117 - // Keyup events
118 - lpUtils.eventHandlers( 'keyup', [
119 - {
120 - selector: EditSection.selectors.elSectionTitleNewInput,
121 - class: this,
122 - callBack: this.changeTitleBeforeAdd.name,
123 - },
124 - {
125 - selector: EditSection.selectors.elSectionTitleInput,
126 - class: this,
127 - callBack: this.changeTitle.name,
128 - },
129 - {
130 - selector: EditSection.selectors.elSectionDesInput,
131 - class: this,
132 - callBack: this.changeDescription.name,
133 - },
134 - ] );
135 -
136 - // Keydown events
137 - lpUtils.eventHandlers( 'keydown', [
138 - {
139 - selector: EditSection.selectors.elSectionTitleNewInput,
140 - class: this,
141 - callBack: this.addSection.name,
142 - checkIsEventEnter: true,
143 - },
144 - {
145 - selector: EditSection.selectors.elSectionDesInput,
146 - class: this,
147 - callBack: this.updateSectionDescription.name,
148 - checkIsEventEnter: true,
149 - },
150 - {
151 - selector: EditSection.selectors.elSectionTitleInput,
152 - class: this,
153 - callBack: this.updateSectionTitle.name,
154 - checkIsEventEnter: true,
155 - },
156 - ] );
157 -
158 - // Focusin events
159 - lpUtils.eventHandlers( 'focusin', [
160 - {
161 - selector: EditSection.selectors.elSectionTitleNewInput,
162 - class: this,
163 - callBack: this.focusTitleNewInput.name,
164 - },
165 - {
166 - selector: EditSection.selectors.elSectionTitleInput,
167 - class: this,
168 - callBack: this.focusTitleInput.name,
169 - },
170 - ] );
171 -
172 - // Focusin events
173 - lpUtils.eventHandlers( 'focusout', [
174 - {
175 - selector: EditSection.selectors.elSectionTitleNewInput,
176 - class: this,
177 - callBack: this.focusTitleNewInput.name,
178 - focusIn: false,
179 - },
180 - {
181 - selector: `${ EditSection.selectors.elSectionTitleInput }`,
182 - class: this,
183 - callBack: this.focusTitleInput.name,
184 - focusIn: false,
185 - },
186 - ] );
187 - }
188 -
189 - /* Typing in new section title input */
190 - changeTitleBeforeAdd( args ) {
191 - const { e, target } = args;
192 - const elSectionTitleNewInput = target;
193 -
194 - const elAddNewSection = elSectionTitleNewInput.closest(
195 - `${ EditSection.selectors.elDivAddNewSection }`
196 - );
197 - if ( ! elAddNewSection ) {
198 - return;
199 - }
200 -
201 - const elBtnAddSection = elAddNewSection.querySelector(
202 - `${ EditSection.selectors.elBtnAddSection }`
203 - );
204 -
205 - const titleValue = elSectionTitleNewInput.value.trim();
206 - if ( titleValue.length === 0 ) {
207 - elBtnAddSection.classList.remove( 'active' );
208 - } else {
209 - elBtnAddSection.classList.add( 'active' );
210 - }
211 - }
212 -
213 - /* Focus on new section title input */
214 - focusTitleNewInput( args ) {
215 - const { e, target, focusIn = true } = args;
216 - const elAddNewSection = target.closest(
217 - `${ EditSection.selectors.elDivAddNewSection }`
218 - );
219 - if ( ! elAddNewSection ) {
220 - return;
221 - }
222 -
223 - if ( focusIn ) {
224 - elAddNewSection.classList.add( 'focus' );
225 - } else {
226 - elAddNewSection.classList.remove( 'focus' );
227 - }
228 - }
229 -
230 - /* Add new section */
231 - addSection( args ) {
232 - const { e, target, callBackNest } = args;
233 -
234 - const elDivAddNewSection = target.closest(
235 - `${ EditSection.selectors.elDivAddNewSection }`
236 - );
237 - if ( ! elDivAddNewSection ) {
238 - return;
239 - }
240 -
241 - e.preventDefault();
242 -
243 - const elSectionTitleNewInput = elDivAddNewSection.querySelector(
244 - `${ EditSection.selectors.elSectionTitleNewInput }`
245 - );
246 - const titleValue = elSectionTitleNewInput.value.trim();
247 - const message = elSectionTitleNewInput.dataset.messEmptyTitle;
248 - if ( titleValue.length === 0 ) {
249 - lpToastify.show( message, 'error' );
250 - return;
251 - }
252 -
253 - // Clear input after add
254 - elSectionTitleNewInput.value = '';
255 - elSectionTitleNewInput.blur();
256 -
257 - // Add and set data for new section
258 - const elSectionClone = this.elCurriculumSections.querySelector(
259 - `${ EditSection.selectors.elSectionClone }`
260 - );
261 - const newSection = elSectionClone.cloneNode( true );
262 - newSection.classList.remove( 'clone' );
263 - lpUtils.lpShowHideEl( newSection, 1 );
264 - lpUtils.lpSetLoadingEl( newSection, 1 );
265 - const elSectionTitleInput = newSection.querySelector(
266 - `${ EditSection.selectors.elSectionTitleInput }`
267 - );
268 - elSectionTitleInput.value = titleValue;
269 - this.elCurriculumSections.insertAdjacentElement(
270 - 'beforeend',
271 - newSection
272 - );
273 - // End
274 -
275 - // Call ajax to add new section
276 - const callBack = {
277 - success: ( response ) => {
278 - const { message, status, data } = response;
279 -
280 - if ( status === 'error' ) {
281 - newSection.remove();
282 - throw message;
283 - } else if ( status === 'success' ) {
284 - const { section } = data;
285 - newSection.dataset.sectionId = section.section_id || '';
286 -
287 - // Initialize EditSectionItem for the new section to make its items sortable
288 - this.editSectionItem.sortAbleItem();
289 -
290 - if (
291 - callBackNest &&
292 - typeof callBackNest.success === 'function'
293 - ) {
294 - args.elSection = newSection;
295 - args.response = response;
296 - callBackNest.success( args );
297 - }
298 - }
299 -
300 - lpToastify.show( message, status );
301 - },
302 - error: ( error ) => {
303 - newSection.remove();
304 - lpToastify.show( error, 'error' );
305 - if (
306 - callBackNest &&
307 - typeof callBackNest.error === 'function'
308 - ) {
309 - args.error = error;
310 - callBackNest.error( args );
311 - }
312 - },
313 - completed: () => {
314 - lpUtils.lpSetLoadingEl( newSection, 0 );
315 - newSection.classList.remove(
316 - `${ EditCourseCurriculum.selectors.elCollapse }`
317 - );
318 - const elSectionDesInput = newSection.querySelector(
319 - `${ EditSection.selectors.elSectionDesInput }`
320 - );
321 - elSectionDesInput.focus();
322 - this.updateCountSections( this.elEditCurriculum );
323 - if (
324 - callBackNest &&
325 - typeof callBackNest.completed === 'function'
326 - ) {
327 - args.elSection = newSection;
328 - callBackNest.completed( args );
329 - }
330 - },
331 - };
332 -
333 - const dataSend = JSON.parse( elSectionTitleNewInput.dataset.send );
334 - dataSend.section_name = titleValue;
335 - window.lpAJAXG.fetchAJAX( dataSend, callBack );
336 - }
337 -
338 - /* Delete section */
339 - deleteSection( args ) {
340 - const { e, target } = args;
341 - const elBtnDeleteSection = target;
342 -
343 - const elEditCurriculum = elBtnDeleteSection.closest(
344 - `${ EditCourseCurriculum.selectors.idElEditCurriculum }`
345 - );
346 -
347 - SweetAlert.fire( {
348 - title: elBtnDeleteSection.dataset.title,
349 - text: elBtnDeleteSection.dataset.content,
350 - icon: 'warning',
351 - showCloseButton: true,
352 - showCancelButton: true,
353 - cancelButtonText: lpData.i18n.cancel,
354 - confirmButtonText: lpData.i18n.yes,
355 - reverseButtons: true,
356 - } ).then( ( result ) => {
357 - if ( result.isConfirmed ) {
358 - const elSection = elBtnDeleteSection.closest( '.section' );
359 - const sectionId = elSection.dataset.sectionId;
360 -
361 - lpUtils.lpSetLoadingEl( elSection, 1 );
362 -
363 - // Call ajax to delete section
364 - const callBack = {
365 - success: ( response ) => {
366 - const { message, status } = response;
367 -
368 - lpToastify.show( message, status );
369 - },
370 - error: ( error ) => {
371 - lpToastify.show( error, 'error' );
372 - },
373 - completed: () => {
374 - lpUtils.lpSetLoadingEl( elSection, 0 );
375 - elSection.remove();
376 - this.editSectionItem.updateCountItems( elSection );
377 - this.updateCountSections( elEditCurriculum );
378 - },
379 - };
380 -
381 - const dataSend = JSON.parse( elBtnDeleteSection.dataset.send );
382 - dataSend.section_id = sectionId;
383 - window.lpAJAXG.fetchAJAX( dataSend, callBack );
384 - }
385 - } );
386 - }
387 -
388 - /* Focus on section title input */
389 - focusTitleInput( args ) {
390 - const { e, target, focusIn = true } = args;
391 - const elSection = target.closest(
392 - `${ EditSection.selectors.elSection }`
393 - );
394 - if ( ! elSection ) {
395 - return;
396 - }
397 -
398 - if ( focusIn ) {
399 - elSection.classList.add( 'focus' );
400 - } else {
401 - elSection.classList.remove( 'focus' );
402 - }
403 - }
404 -
405 - /* Set focus on section title input */
406 - setFocusTitleInput( args ) {
407 - const { e, target } = args;
408 -
409 - const elSection = target.closest(
410 - `${ EditSection.selectors.elSection }`
411 - );
412 - if ( ! elSection ) {
413 - return;
414 - }
415 -
416 - const elSectionTitleInput = elSection.querySelector(
417 - `${ EditSection.selectors.elSectionTitleInput }`
418 - );
419 - elSectionTitleInput.setSelectionRange(
420 - elSectionTitleInput.value.length,
421 - elSectionTitleInput.value.length
422 - );
423 - elSectionTitleInput.focus();
424 - }
425 -
426 - /* Typing in section title input */
427 - changeTitle( args ) {
428 - const { e, target } = args;
429 - const elSectionTitleInput = target;
430 - const elSection = elSectionTitleInput.closest(
431 - `${ EditSection.selectors.elSection }`
432 - );
433 - const titleValue = elSectionTitleInput.value.trim();
434 - const titleValueOld = elSectionTitleInput.dataset.old || '';
435 -
436 - if ( titleValue === titleValueOld ) {
437 - elSection.classList.remove( 'editing' );
438 - } else {
439 - elSection.classList.add( 'editing' );
440 - }
441 - }
442 -
443 - /* Update section title to server */
444 - updateSectionTitle( args ) {
445 - const { e, target } = args;
446 - const elSection = target.closest(
447 - `${ EditSection.selectors.elSection }`
448 - );
449 - if ( ! elSection ) {
450 - return;
451 - }
452 -
453 - e.preventDefault();
454 -
455 - const elSectionTitleInput = elSection.querySelector(
456 - `${ EditSection.selectors.elSectionTitleInput }`
457 - );
458 - if ( ! elSectionTitleInput ) {
459 - return;
460 - }
461 -
462 - const sectionId = elSection.dataset.sectionId;
463 - const titleValue = elSectionTitleInput.value.trim();
464 - const titleValueOld = elSectionTitleInput.dataset.old || '';
465 - const message = elSectionTitleInput.dataset.messEmptyTitle;
466 - if ( titleValue.length === 0 ) {
467 - lpToastify.show( message, 'error' );
468 - return;
469 - }
470 -
471 - if ( titleValue === titleValueOld ) {
472 - return;
473 - }
474 -
475 - elSectionTitleInput.blur();
476 - lpUtils.lpSetLoadingEl( elSection, 1 );
477 -
478 - // Call ajax to update section title
479 - const callBack = {
480 - success: ( response ) => {
481 - const { message, status } = response;
482 -
483 - lpToastify.show( message, status );
484 -
485 - if ( status === 'success' ) {
486 - elSectionTitleInput.dataset.old = titleValue;
487 - }
488 - },
489 - error: ( error ) => {
490 - lpToastify.show( error, 'error' );
491 - },
492 - completed: () => {
493 - lpUtils.lpSetLoadingEl( elSection, 0 );
494 - elSection.classList.remove( 'editing' );
495 - },
496 - };
497 -
498 - const dataSend = JSON.parse( elSectionTitleInput.dataset.send );
499 - dataSend.section_id = sectionId;
500 - dataSend.section_name = titleValue;
501 - window.lpAJAXG.fetchAJAX( dataSend, callBack );
502 - }
503 -
504 - /* Cancel updating section title */
505 - cancelSectionTitle( args ) {
506 - const { e, target } = args;
507 - const elBtnCancelUpdateTitle = target.closest(
508 - `${ EditSection.selectors.elBtnCancelUpdateTitle }`
509 - );
510 - if ( ! elBtnCancelUpdateTitle ) {
511 - return;
512 - }
513 -
514 - const elSection = elBtnCancelUpdateTitle.closest(
515 - `${ EditSection.selectors.elSection }`
516 - );
517 - const elSectionTitleInput = elSection.querySelector(
518 - `${ EditSection.selectors.elSectionTitleInput }`
519 - );
520 - elSectionTitleInput.value = elSectionTitleInput.dataset.old || '';
521 - elSection.classList.remove( 'editing' );
522 - }
523 -
524 - /* Update section description to server */
525 - updateSectionDescription( args ) {
526 - const { e, target, callBackNest } = args;
527 -
528 - const elSectionDesc = target.closest(
529 - `${ EditSection.selectors.elSectionDesc }`
530 - );
531 - if ( ! elSectionDesc ) {
532 - return;
533 - }
534 -
535 - const elSectionDesInput = elSectionDesc.querySelector(
536 - `${ EditSection.selectors.elSectionDesInput }`
537 - );
538 - if ( ! elSectionDesInput ) {
539 - return;
540 - }
541 -
542 - e.preventDefault();
543 -
544 - const elSection = elSectionDesInput.closest(
545 - `${ EditSection.selectors.elSection }`
546 - );
547 - const sectionId = elSection.dataset.sectionId;
548 - const descValue = elSectionDesInput.value.trim();
549 - const descValueOld = elSectionDesInput.dataset.old || '';
550 -
551 - if ( descValue === descValueOld ) {
552 - return;
553 - }
554 -
555 - lpUtils.lpSetLoadingEl( elSection, 1 );
556 -
557 - const callBack = {
558 - success: ( response ) => {
559 - const { message, status } = response;
560 -
561 - if (
562 - callBackNest &&
563 - typeof callBackNest.success === 'function'
564 - ) {
565 - args.elSection = elSection;
566 - args.response = response;
567 - callBackNest.success( args );
568 - }
569 -
570 - lpToastify.show( message, status );
571 - },
572 - error: ( error ) => {
573 - lpToastify.show( error, 'error' );
574 - if (
575 - callBackNest &&
576 - typeof callBackNest.error === 'function'
577 - ) {
578 - callBackNest.error( elSection, error );
579 - }
580 - },
581 - completed: () => {
582 - lpUtils.lpSetLoadingEl( elSection, 0 );
583 - const elSectionDesc = elSectionDesInput.closest(
584 - `${ EditSection.selectors.elSectionDesc }`
585 - );
586 - elSectionDesc.classList.remove( 'editing' );
587 - elSectionDesInput.dataset.old = descValue;
588 - if (
589 - callBackNest &&
590 - typeof callBackNest.completed === 'function'
591 - ) {
592 - callBackNest.completed( elSection );
593 - }
594 - },
595 - };
596 -
597 - const dataSend = JSON.parse( elSectionDesInput.dataset.send );
598 - dataSend.section_id = sectionId;
599 - dataSend.section_description = descValue;
600 - window.lpAJAXG.fetchAJAX( dataSend, callBack );
601 - }
602 -
603 - /* Cancel updating section description */
604 - cancelSectionDescription( args ) {
605 - const { e, target } = args;
606 - const elSectionDesc = target.closest(
607 - `${ EditSection.selectors.elSectionDesc }`
608 - );
609 - const elSectionDesInput = elSectionDesc.querySelector(
610 - `${ EditSection.selectors.elSectionDesInput }`
611 - );
612 - elSectionDesInput.value = elSectionDesInput.dataset.old || '';
613 - elSectionDesc.classList.remove( 'editing' );
614 - }
615 -
616 - /* Typing in description input */
617 - changeDescription( ags ) {
618 - const { e, target } = ags;
619 - const elSectionDesInput = target.closest(
620 - `${ EditSection.selectors.elSectionDesInput }`
621 - );
622 - if ( ! elSectionDesInput ) {
623 - return;
624 - }
625 -
626 - const elSectionDesc = elSectionDesInput.closest(
627 - `${ EditSection.selectors.elSectionDesc }`
628 - );
629 - const descValue = elSectionDesInput.value.trim();
630 - const descValueOld = elSectionDesInput.dataset.old || '';
631 -
632 - if ( descValue === descValueOld ) {
633 - elSectionDesc.classList.remove( 'editing' );
634 - } else {
635 - elSectionDesc.classList.add( 'editing' );
636 - }
637 - }
638 -
639 - toggleSectionAll( args ) {
640 - const { e, target } = args;
641 - const elToggleAllSections = target.closest(
642 - `${ EditCourseCurriculum.selectors.elToggleAllSections }`
643 - );
644 - if ( ! elToggleAllSections ) {
645 - return;
646 - }
647 -
648 - const elEditCurriculum = elToggleAllSections.closest(
649 - `${ EditCourseCurriculum.selectors.idElEditCurriculum }`
650 - );
651 - const elSections = elEditCurriculum.querySelectorAll(
652 - `${ EditSection.selectors.elSection }:not(.clone)`
653 - );
654 -
655 - elToggleAllSections.classList.toggle(
656 - `${ EditCourseCurriculum.selectors.elCollapse }`
657 - );
658 -
659 - elSections.forEach( ( el ) => {
660 - const shouldCollapse = elToggleAllSections.classList.contains(
661 - `${ EditCourseCurriculum.selectors.elCollapse }`
662 - );
663 - el.classList.toggle(
664 - `${ EditCourseCurriculum.selectors.elCollapse }`,
665 - shouldCollapse
666 - );
667 - } );
668 - }
669 -
670 - /* Toggle section */
671 - toggleSection( args ) {
672 - const { e, target } = args;
673 - const elSection = target.closest(
674 - `${ EditSection.selectors.elSection }`
675 - );
676 -
677 - const elCurriculumSections = elSection.closest(
678 - `${ EditCourseCurriculum.selectors.elCurriculumSections }`
679 - );
680 - if ( ! elCurriculumSections ) {
681 - return;
682 - }
683 -
684 - // Toggle section
685 - elSection.classList.toggle(
686 - `${ EditCourseCurriculum.selectors.elCollapse }`
687 - );
688 -
689 - // Check all sections collapsed
690 - this.checkAllSectionsCollapsed();
691 - }
692 -
693 - /* Check if all sections are collapsed */
694 - checkAllSectionsCollapsed() {
695 - const elSections = this.elEditCurriculum.querySelectorAll(
696 - `${ EditSection.selectors.elSection }:not(.clone)`
697 - );
698 - const elToggleAllSections = this.elEditCurriculum.querySelector(
699 - `${ EditCourseCurriculum.selectors.elToggleAllSections }`
700 - );
701 -
702 - let isAllExpand = true;
703 - elSections.forEach( ( el ) => {
704 - if (
705 - el.classList.contains(
706 - `${ EditCourseCurriculum.selectors.elCollapse }`
707 - )
708 - ) {
709 - isAllExpand = false;
710 - return false; // Break the loop
711 - }
712 - } );
713 -
714 - if ( isAllExpand ) {
715 - elToggleAllSections.classList.remove(
716 - `${ EditCourseCurriculum.selectors.elCollapse }`
717 - );
718 - } else {
719 - elToggleAllSections.classList.add(
720 - `${ EditCourseCurriculum.selectors.elCollapse }`
721 - );
722 - }
723 - }
724 -
725 - /* Sortable sections, drag and drop to change section position */
726 - sortAbleSection() {
727 - let isUpdateSectionPosition = 0;
728 - let timeout;
729 -
730 - new Sortable( this.elCurriculumSections, {
731 - handle: '.drag',
732 - animation: 150,
733 - onEnd: ( evt ) => {
734 - const target = evt.item;
735 - if ( ! isUpdateSectionPosition ) {
736 - return;
737 - }
738 -
739 - const elSection = target.closest(
740 - `${ EditSection.selectors.elSection }`
741 - );
742 - const elSections = this.elCurriculumSections.querySelectorAll(
743 - `${ EditSection.selectors.elSection }`
744 - );
745 - const sectionIds = [];
746 -
747 - elSections.forEach( ( elSection ) => {
748 - const sectionId = elSection.dataset.sectionId;
749 - sectionIds.push( sectionId );
750 - } );
751 -
752 - // Call ajax to update section position
753 - const callBack = {
754 - success: ( response ) => {
755 - const { message, status } = response;
756 -
757 - lpToastify.show( message, status );
758 - },
759 - error: ( error ) => {
760 - lpToastify.show( error, 'error' );
761 - },
762 - completed: () => {
763 - lpUtils.lpSetLoadingEl( elSection, 0 );
764 - isUpdateSectionPosition = 0;
765 - },
766 - };
767 -
768 - const dataSend = {
769 - action: 'course_update_section_position',
770 - course_id: this.courseId,
771 - new_position: sectionIds,
772 - args: { id_url: 'course-update-section-position' },
773 - };
774 -
775 - clearTimeout( timeout );
776 - timeout = setTimeout( () => {
777 - lpUtils.lpSetLoadingEl( elSection, 1 );
778 - window.lpAJAXG.fetchAJAX( dataSend, callBack );
779 - }, 1000 );
780 - },
781 - onMove: ( evt ) => {
782 - clearTimeout( timeout );
783 - },
784 - onUpdate: ( evt ) => {
785 - isUpdateSectionPosition = 1;
786 - },
787 - } );
788 - }
789 -
790 - /* Update count sections, when add or delete section */
791 - updateCountSections( elEditCurriculum ) {
792 - const elCountSections = elEditCurriculum.querySelector(
793 - `${ EditSection.selectors.elCountSections }`
794 - );
795 - const elSections = elEditCurriculum.querySelectorAll(
796 - `${ EditSection.selectors.elSection }:not(.clone)`
797 - );
798 - const sectionsCount = elSections.length;
799 -
800 - elCountSections.dataset.count = sectionsCount;
801 - elCountSections.querySelector( '.count' ).textContent = sectionsCount;
802 - }
803 -}
1 +/**
2 + * Edit Section Script on Curriculum
3 + *
4 + * @since 4.2.8.6
5 + * @version 1.0.3
6 + */
7 +import SweetAlert from 'sweetalert2';
8 +import Sortable from 'sortablejs';
9 +import * as lpUtils from 'lpAssetsJsPath/utils.js';
10 +import * as lpToastify from 'lpAssetsJsPath/lpToastify.js';
11 +import { EditSectionItem } from './edit-section-item.js';
12 +import { EditCourseCurriculum } from '../edit-curriculum.js';
13 +
14 +export class EditSection {
15 + constructor() {
16 + this.courseId = null;
17 + this.elEditCurriculum = null;
18 + this.elCurriculumSections = null;
19 + this.editSectionItem = new EditSectionItem();
20 + }
21 +
22 + static selectors = {
23 + elSection: '.section',
24 + elDivAddNewSection: '.add-new-section',
25 + elSectionClone: '.section.clone',
26 + elSectionTitleNewInput: '.lp-section-title-new-input',
27 + elSectionTitleInput: '.lp-section-title-input',
28 + etBtnEditTitle: '.lp-btn-edit-section-title',
29 + elSectionDesInput: '.lp-section-description-input',
30 + elBtnAddSection: '.lp-btn-add-section',
31 + elBtnUpdateTitle: '.lp-btn-update-section-title',
32 + elBtnUpdateDes: '.lp-btn-update-section-description',
33 + elBtnCancelUpdateTitle: '.lp-btn-cancel-update-section-title',
34 + elBtnCancelUpdateDes: '.lp-btn-cancel-update-section-description',
35 + elBtnDeleteSection: '.lp-btn-delete-section',
36 + elSectionDesc: '.section-description',
37 + elSectionToggle: '.section-toggle',
38 + elCountSections: '.count-sections',
39 + };
40 +
41 + init() {
42 + this.elEditCurriculum = document.querySelector(
43 + `${ EditCourseCurriculum.selectors.idElEditCurriculum }`
44 + );
45 + this.elCurriculumSections = this.elEditCurriculum.querySelector(
46 + `${ EditCourseCurriculum.selectors.elCurriculumSections }`
47 + );
48 + const elLPTarget = this.elEditCurriculum.closest(
49 + `${ EditCourseCurriculum.selectors.LPTarget }`
50 + );
51 + const dataSend = window.lpAJAXG.getDataSetCurrent( elLPTarget );
52 + this.courseId = dataSend.args.course_id;
53 +
54 + this.editSectionItem.init();
55 +
56 + this.events();
57 + this.sortAbleSection();
58 + }
59 +
60 + events() {
61 + // Check and attach events only once
62 + if ( EditSection._loadedEvents ) {
63 + return;
64 + }
65 +
66 + EditSection._loadedEvents = this;
67 +
68 + // Click events
69 + lpUtils.eventHandlers( 'click', [
70 + {
71 + selector: EditSection.selectors.elBtnAddSection,
72 + class: this,
73 + callBack: this.addSection.name,
74 + },
75 + {
76 + selector: `${ EditSection.selectors.elBtnUpdateDes }`,
77 + class: this,
78 + callBack: this.updateSectionDescription.name,
79 + },
80 + {
81 + selector: `${ EditSection.selectors.etBtnEditTitle }`,
82 + class: this,
83 + callBack: this.setFocusTitleInput.name,
84 + },
85 + {
86 + selector: `${ EditSection.selectors.elSectionToggle }`,
87 + class: this,
88 + callBack: this.toggleSection.name,
89 + },
90 + {
91 + selector: `${ EditSection.selectors.elBtnCancelUpdateDes }`,
92 + class: this,
93 + callBack: this.cancelSectionDescription.name,
94 + },
95 + {
96 + selector: `${ EditSection.selectors.elBtnDeleteSection }`,
97 + class: this,
98 + callBack: this.deleteSection.name,
99 + },
100 + {
101 + selector: `${ EditSection.selectors.elBtnUpdateTitle }`,
102 + class: this,
103 + callBack: this.updateSectionTitle.name,
104 + },
105 + {
106 + selector: `${ EditSection.selectors.elBtnCancelUpdateTitle }`,
107 + class: this,
108 + callBack: this.cancelSectionTitle.name,
109 + },
110 + {
111 + selector: EditCourseCurriculum.selectors.elToggleAllSections,
112 + class: this,
113 + callBack: this.toggleSectionAll.name,
114 + },
115 + ] );
116 +
117 + // Keyup events
118 + lpUtils.eventHandlers( 'keyup', [
119 + {
120 + selector: EditSection.selectors.elSectionTitleNewInput,
121 + class: this,
122 + callBack: this.changeTitleBeforeAdd.name,
123 + },
124 + {
125 + selector: EditSection.selectors.elSectionTitleInput,
126 + class: this,
127 + callBack: this.changeTitle.name,
128 + },
129 + {
130 + selector: EditSection.selectors.elSectionDesInput,
131 + class: this,
132 + callBack: this.changeDescription.name,
133 + },
134 + ] );
135 +
136 + // Keydown events
137 + lpUtils.eventHandlers( 'keydown', [
138 + {
139 + selector: EditSection.selectors.elSectionTitleNewInput,
140 + class: this,
141 + callBack: this.addSection.name,
142 + checkIsEventEnter: true,
143 + },
144 + {
145 + selector: EditSection.selectors.elSectionDesInput,
146 + class: this,
147 + callBack: this.updateSectionDescription.name,
148 + checkIsEventEnter: true,
149 + },
150 + {
151 + selector: EditSection.selectors.elSectionTitleInput,
152 + class: this,
153 + callBack: this.updateSectionTitle.name,
154 + checkIsEventEnter: true,
155 + },
156 + ] );
157 +
158 + // Focusin events
159 + lpUtils.eventHandlers( 'focusin', [
160 + {
161 + selector: EditSection.selectors.elSectionTitleNewInput,
162 + class: this,
163 + callBack: this.focusTitleNewInput.name,
164 + },
165 + {
166 + selector: EditSection.selectors.elSectionTitleInput,
167 + class: this,
168 + callBack: this.focusTitleInput.name,
169 + },
170 + ] );
171 +
172 + // Focusin events
173 + lpUtils.eventHandlers( 'focusout', [
174 + {
175 + selector: EditSection.selectors.elSectionTitleNewInput,
176 + class: this,
177 + callBack: this.focusTitleNewInput.name,
178 + focusIn: false,
179 + },
180 + {
181 + selector: `${ EditSection.selectors.elSectionTitleInput }`,
182 + class: this,
183 + callBack: this.focusTitleInput.name,
184 + focusIn: false,
185 + },
186 + ] );
187 + }
188 +
189 + /* Typing in new section title input */
190 + changeTitleBeforeAdd( args ) {
191 + const { e, target } = args;
192 + const elSectionTitleNewInput = target;
193 +
194 + const elAddNewSection = elSectionTitleNewInput.closest(
195 + `${ EditSection.selectors.elDivAddNewSection }`
196 + );
197 + if ( ! elAddNewSection ) {
198 + return;
199 + }
200 +
201 + const elBtnAddSection = elAddNewSection.querySelector(
202 + `${ EditSection.selectors.elBtnAddSection }`
203 + );
204 +
205 + const titleValue = elSectionTitleNewInput.value.trim();
206 + if ( titleValue.length === 0 ) {
207 + elBtnAddSection.classList.remove( 'active' );
208 + } else {
209 + elBtnAddSection.classList.add( 'active' );
210 + }
211 + }
212 +
213 + /* Focus on new section title input */
214 + focusTitleNewInput( args ) {
215 + const { e, target, focusIn = true } = args;
216 + const elAddNewSection = target.closest(
217 + `${ EditSection.selectors.elDivAddNewSection }`
218 + );
219 + if ( ! elAddNewSection ) {
220 + return;
221 + }
222 +
223 + if ( focusIn ) {
224 + elAddNewSection.classList.add( 'focus' );
225 + } else {
226 + elAddNewSection.classList.remove( 'focus' );
227 + }
228 + }
229 +
230 + /* Add new section */
231 + addSection( args ) {
232 + const { e, target, callBackNest } = args;
233 +
234 + const elDivAddNewSection = target.closest(
235 + `${ EditSection.selectors.elDivAddNewSection }`
236 + );
237 + if ( ! elDivAddNewSection ) {
238 + return;
239 + }
240 +
241 + e.preventDefault();
242 +
243 + const elSectionTitleNewInput = elDivAddNewSection.querySelector(
244 + `${ EditSection.selectors.elSectionTitleNewInput }`
245 + );
246 + const titleValue = elSectionTitleNewInput.value.trim();
247 + const message = elSectionTitleNewInput.dataset.messEmptyTitle;
248 + if ( titleValue.length === 0 ) {
249 + lpToastify.show( message, 'error' );
250 + return;
251 + }
252 +
253 + // Clear input after add
254 + elSectionTitleNewInput.value = '';
255 + elSectionTitleNewInput.blur();
256 +
257 + // Add and set data for new section
258 + const elSectionClone = this.elCurriculumSections.querySelector(
259 + `${ EditSection.selectors.elSectionClone }`
260 + );
261 + const newSection = elSectionClone.cloneNode( true );
262 + newSection.classList.remove( 'clone' );
263 + lpUtils.lpShowHideEl( newSection, 1 );
264 + lpUtils.lpSetLoadingEl( newSection, 1 );
265 + const elSectionTitleInput = newSection.querySelector(
266 + `${ EditSection.selectors.elSectionTitleInput }`
267 + );
268 + elSectionTitleInput.value = titleValue;
269 + this.elCurriculumSections.insertAdjacentElement(
270 + 'beforeend',
271 + newSection
272 + );
273 + // End
274 +
275 + // Call ajax to add new section
276 + const callBack = {
277 + success: ( response ) => {
278 + const { message, status, data } = response;
279 +
280 + if ( status === 'error' ) {
281 + newSection.remove();
282 + throw message;
283 + } else if ( status === 'success' ) {
284 + const { section } = data;
285 + newSection.dataset.sectionId = section.section_id || '';
286 +
287 + // Initialize EditSectionItem for the new section to make its items sortable
288 + this.editSectionItem.sortAbleItem();
289 +
290 + if (
291 + callBackNest &&
292 + typeof callBackNest.success === 'function'
293 + ) {
294 + args.elSection = newSection;
295 + args.response = response;
296 + callBackNest.success( args );
297 + }
298 + }
299 +
300 + lpToastify.show( message, status );
301 + },
302 + error: ( error ) => {
303 + newSection.remove();
304 + lpToastify.show( error, 'error' );
305 + if (
306 + callBackNest &&
307 + typeof callBackNest.error === 'function'
308 + ) {
309 + args.error = error;
310 + callBackNest.error( args );
311 + }
312 + },
313 + completed: () => {
314 + lpUtils.lpSetLoadingEl( newSection, 0 );
315 + newSection.classList.remove(
316 + `${ EditCourseCurriculum.selectors.elCollapse }`
317 + );
318 + const elSectionDesInput = newSection.querySelector(
319 + `${ EditSection.selectors.elSectionDesInput }`
320 + );
321 + elSectionDesInput.focus();
322 + this.updateCountSections( this.elEditCurriculum );
323 + if (
324 + callBackNest &&
325 + typeof callBackNest.completed === 'function'
326 + ) {
327 + args.elSection = newSection;
328 + callBackNest.completed( args );
329 + }
330 + },
331 + };
332 +
333 + const dataSend = JSON.parse( elSectionTitleNewInput.dataset.send );
334 + dataSend.section_name = titleValue;
335 + window.lpAJAXG.fetchAJAX( dataSend, callBack );
336 + }
337 +
338 + /* Delete section */
339 + deleteSection( args ) {
340 + const { e, target } = args;
341 + const elBtnDeleteSection = target;
342 +
343 + const elEditCurriculum = elBtnDeleteSection.closest(
344 + `${ EditCourseCurriculum.selectors.idElEditCurriculum }`
345 + );
346 +
347 + SweetAlert.fire( {
348 + title: elBtnDeleteSection.dataset.title,
349 + text: elBtnDeleteSection.dataset.content,
350 + icon: 'warning',
351 + showCloseButton: true,
352 + showCancelButton: true,
353 + cancelButtonText: lpData.i18n.cancel,
354 + confirmButtonText: lpData.i18n.yes,
355 + reverseButtons: true,
356 + } ).then( ( result ) => {
357 + if ( result.isConfirmed ) {
358 + const elSection = elBtnDeleteSection.closest( '.section' );
359 + const sectionId = elSection.dataset.sectionId;
360 +
361 + lpUtils.lpSetLoadingEl( elSection, 1 );
362 +
363 + // Call ajax to delete section
364 + const callBack = {
365 + success: ( response ) => {
366 + const { message, status } = response;
367 +
368 + lpToastify.show( message, status );
369 + },
370 + error: ( error ) => {
371 + lpToastify.show( error, 'error' );
372 + },
373 + completed: () => {
374 + lpUtils.lpSetLoadingEl( elSection, 0 );
375 + elSection.remove();
376 + this.editSectionItem.updateCountItems( elSection );
377 + this.updateCountSections( elEditCurriculum );
378 + },
379 + };
380 +
381 + const dataSend = JSON.parse( elBtnDeleteSection.dataset.send );
382 + dataSend.section_id = sectionId;
383 + window.lpAJAXG.fetchAJAX( dataSend, callBack );
384 + }
385 + } );
386 + }
387 +
388 + /* Focus on section title input */
389 + focusTitleInput( args ) {
390 + const { e, target, focusIn = true } = args;
391 + const elSection = target.closest(
392 + `${ EditSection.selectors.elSection }`
393 + );
394 + if ( ! elSection ) {
395 + return;
396 + }
397 +
398 + if ( focusIn ) {
399 + elSection.classList.add( 'focus' );
400 + } else {
401 + elSection.classList.remove( 'focus' );
402 + }
403 + }
404 +
405 + /* Set focus on section title input */
406 + setFocusTitleInput( args ) {
407 + const { e, target } = args;
408 +
409 + const elSection = target.closest(
410 + `${ EditSection.selectors.elSection }`
411 + );
412 + if ( ! elSection ) {
413 + return;
414 + }
415 +
416 + const elSectionTitleInput = elSection.querySelector(
417 + `${ EditSection.selectors.elSectionTitleInput }`
418 + );
419 + elSectionTitleInput.setSelectionRange(
420 + elSectionTitleInput.value.length,
421 + elSectionTitleInput.value.length
422 + );
423 + elSectionTitleInput.focus();
424 + }
425 +
426 + /* Typing in section title input */
427 + changeTitle( args ) {
428 + const { e, target } = args;
429 + const elSectionTitleInput = target;
430 + const elSection = elSectionTitleInput.closest(
431 + `${ EditSection.selectors.elSection }`
432 + );
433 + const titleValue = elSectionTitleInput.value.trim();
434 + const titleValueOld = elSectionTitleInput.dataset.old || '';
435 +
436 + if ( titleValue === titleValueOld ) {
437 + elSection.classList.remove( 'editing' );
438 + } else {
439 + elSection.classList.add( 'editing' );
440 + }
441 + }
442 +
443 + /* Update section title to server */
444 + updateSectionTitle( args ) {
445 + const { e, target } = args;
446 + const elSection = target.closest(
447 + `${ EditSection.selectors.elSection }`
448 + );
449 + if ( ! elSection ) {
450 + return;
451 + }
452 +
453 + e.preventDefault();
454 +
455 + const elSectionTitleInput = elSection.querySelector(
456 + `${ EditSection.selectors.elSectionTitleInput }`
457 + );
458 + if ( ! elSectionTitleInput ) {
459 + return;
460 + }
461 +
462 + const sectionId = elSection.dataset.sectionId;
463 + const titleValue = elSectionTitleInput.value.trim();
464 + const titleValueOld = elSectionTitleInput.dataset.old || '';
465 + const message = elSectionTitleInput.dataset.messEmptyTitle;
466 + if ( titleValue.length === 0 ) {
467 + lpToastify.show( message, 'error' );
468 + return;
469 + }
470 +
471 + if ( titleValue === titleValueOld ) {
472 + return;
473 + }
474 +
475 + elSectionTitleInput.blur();
476 + lpUtils.lpSetLoadingEl( elSection, 1 );
477 +
478 + // Call ajax to update section title
479 + const callBack = {
480 + success: ( response ) => {
481 + const { message, status } = response;
482 +
483 + lpToastify.show( message, status );
484 +
485 + if ( status === 'success' ) {
486 + elSectionTitleInput.dataset.old = titleValue;
487 + }
488 + },
489 + error: ( error ) => {
490 + lpToastify.show( error, 'error' );
491 + },
492 + completed: () => {
493 + lpUtils.lpSetLoadingEl( elSection, 0 );
494 + elSection.classList.remove( 'editing' );
495 + },
496 + };
497 +
498 + const dataSend = JSON.parse( elSectionTitleInput.dataset.send );
499 + dataSend.section_id = sectionId;
500 + dataSend.section_name = titleValue;
501 + window.lpAJAXG.fetchAJAX( dataSend, callBack );
502 + }
503 +
504 + /* Cancel updating section title */
505 + cancelSectionTitle( args ) {
506 + const { e, target } = args;
507 + const elBtnCancelUpdateTitle = target.closest(
508 + `${ EditSection.selectors.elBtnCancelUpdateTitle }`
509 + );
510 + if ( ! elBtnCancelUpdateTitle ) {
511 + return;
512 + }
513 +
514 + const elSection = elBtnCancelUpdateTitle.closest(
515 + `${ EditSection.selectors.elSection }`
516 + );
517 + const elSectionTitleInput = elSection.querySelector(
518 + `${ EditSection.selectors.elSectionTitleInput }`
519 + );
520 + elSectionTitleInput.value = elSectionTitleInput.dataset.old || '';
521 + elSection.classList.remove( 'editing' );
522 + }
523 +
524 + /* Update section description to server */
525 + updateSectionDescription( args ) {
526 + const { e, target, callBackNest } = args;
527 +
528 + const elSectionDesc = target.closest(
529 + `${ EditSection.selectors.elSectionDesc }`
530 + );
531 + if ( ! elSectionDesc ) {
532 + return;
533 + }
534 +
535 + const elSectionDesInput = elSectionDesc.querySelector(
536 + `${ EditSection.selectors.elSectionDesInput }`
537 + );
538 + if ( ! elSectionDesInput ) {
539 + return;
540 + }
541 +
542 + e.preventDefault();
543 +
544 + const elSection = elSectionDesInput.closest(
545 + `${ EditSection.selectors.elSection }`
546 + );
547 + const sectionId = elSection.dataset.sectionId;
548 + const descValue = elSectionDesInput.value.trim();
549 + const descValueOld = elSectionDesInput.dataset.old || '';
550 +
551 + if ( descValue === descValueOld ) {
552 + return;
553 + }
554 +
555 + lpUtils.lpSetLoadingEl( elSection, 1 );
556 +
557 + const callBack = {
558 + success: ( response ) => {
559 + const { message, status } = response;
560 +
561 + if (
562 + callBackNest &&
563 + typeof callBackNest.success === 'function'
564 + ) {
565 + args.elSection = elSection;
566 + args.response = response;
567 + callBackNest.success( args );
568 + }
569 +
570 + lpToastify.show( message, status );
571 + },
572 + error: ( error ) => {
573 + lpToastify.show( error, 'error' );
574 + if (
575 + callBackNest &&
576 + typeof callBackNest.error === 'function'
577 + ) {
578 + callBackNest.error( elSection, error );
579 + }
580 + },
581 + completed: () => {
582 + lpUtils.lpSetLoadingEl( elSection, 0 );
583 + const elSectionDesc = elSectionDesInput.closest(
584 + `${ EditSection.selectors.elSectionDesc }`
585 + );
586 + elSectionDesc.classList.remove( 'editing' );
587 + elSectionDesInput.dataset.old = descValue;
588 + if (
589 + callBackNest &&
590 + typeof callBackNest.completed === 'function'
591 + ) {
592 + callBackNest.completed( elSection );
593 + }
594 + },
595 + };
596 +
597 + const dataSend = JSON.parse( elSectionDesInput.dataset.send );
598 + dataSend.section_id = sectionId;
599 + dataSend.section_description = descValue;
600 + window.lpAJAXG.fetchAJAX( dataSend, callBack );
601 + }
602 +
603 + /* Cancel updating section description */
604 + cancelSectionDescription( args ) {
605 + const { e, target } = args;
606 + const elSectionDesc = target.closest(
607 + `${ EditSection.selectors.elSectionDesc }`
608 + );
609 + const elSectionDesInput = elSectionDesc.querySelector(
610 + `${ EditSection.selectors.elSectionDesInput }`
611 + );
612 + elSectionDesInput.value = elSectionDesInput.dataset.old || '';
613 + elSectionDesc.classList.remove( 'editing' );
614 + }
615 +
616 + /* Typing in description input */
617 + changeDescription( ags ) {
618 + const { e, target } = ags;
619 + const elSectionDesInput = target.closest(
620 + `${ EditSection.selectors.elSectionDesInput }`
621 + );
622 + if ( ! elSectionDesInput ) {
623 + return;
624 + }
625 +
626 + const elSectionDesc = elSectionDesInput.closest(
627 + `${ EditSection.selectors.elSectionDesc }`
628 + );
629 + const descValue = elSectionDesInput.value.trim();
630 + const descValueOld = elSectionDesInput.dataset.old || '';
631 +
632 + if ( descValue === descValueOld ) {
633 + elSectionDesc.classList.remove( 'editing' );
634 + } else {
635 + elSectionDesc.classList.add( 'editing' );
636 + }
637 + }
638 +
639 + toggleSectionAll( args ) {
640 + const { e, target } = args;
641 + const elToggleAllSections = target.closest(
642 + `${ EditCourseCurriculum.selectors.elToggleAllSections }`
643 + );
644 + if ( ! elToggleAllSections ) {
645 + return;
646 + }
647 +
648 + const elEditCurriculum = elToggleAllSections.closest(
649 + `${ EditCourseCurriculum.selectors.idElEditCurriculum }`
650 + );
651 + const elSections = elEditCurriculum.querySelectorAll(
652 + `${ EditSection.selectors.elSection }:not(.clone)`
653 + );
654 +
655 + elToggleAllSections.classList.toggle(
656 + `${ EditCourseCurriculum.selectors.elCollapse }`
657 + );
658 +
659 + elSections.forEach( ( el ) => {
660 + const shouldCollapse = elToggleAllSections.classList.contains(
661 + `${ EditCourseCurriculum.selectors.elCollapse }`
662 + );
663 + el.classList.toggle(
664 + `${ EditCourseCurriculum.selectors.elCollapse }`,
665 + shouldCollapse
666 + );
667 + } );
668 + }
669 +
670 + /* Toggle section */
671 + toggleSection( args ) {
672 + const { e, target } = args;
673 + const elSection = target.closest(
674 + `${ EditSection.selectors.elSection }`
675 + );
676 +
677 + const elCurriculumSections = elSection.closest(
678 + `${ EditCourseCurriculum.selectors.elCurriculumSections }`
679 + );
680 + if ( ! elCurriculumSections ) {
681 + return;
682 + }
683 +
684 + // Toggle section
685 + elSection.classList.toggle(
686 + `${ EditCourseCurriculum.selectors.elCollapse }`
687 + );
688 +
689 + // Check all sections collapsed
690 + this.checkAllSectionsCollapsed();
691 + }
692 +
693 + /* Check if all sections are collapsed */
694 + checkAllSectionsCollapsed() {
695 + const elSections = this.elEditCurriculum.querySelectorAll(
696 + `${ EditSection.selectors.elSection }:not(.clone)`
697 + );
698 + const elToggleAllSections = this.elEditCurriculum.querySelector(
699 + `${ EditCourseCurriculum.selectors.elToggleAllSections }`
700 + );
701 +
702 + let isAllExpand = true;
703 + elSections.forEach( ( el ) => {
704 + if (
705 + el.classList.contains(
706 + `${ EditCourseCurriculum.selectors.elCollapse }`
707 + )
708 + ) {
709 + isAllExpand = false;
710 + return false; // Break the loop
711 + }
712 + } );
713 +
714 + if ( isAllExpand ) {
715 + elToggleAllSections.classList.remove(
716 + `${ EditCourseCurriculum.selectors.elCollapse }`
717 + );
718 + } else {
719 + elToggleAllSections.classList.add(
720 + `${ EditCourseCurriculum.selectors.elCollapse }`
721 + );
722 + }
723 + }
724 +
725 + /* Sortable sections, drag and drop to change section position */
726 + sortAbleSection() {
727 + let isUpdateSectionPosition = 0;
728 + let timeout;
729 +
730 + new Sortable( this.elCurriculumSections, {
731 + handle: '.drag',
732 + animation: 150,
733 + onEnd: ( evt ) => {
734 + const target = evt.item;
735 + if ( ! isUpdateSectionPosition ) {
736 + return;
737 + }
738 +
739 + const elSection = target.closest(
740 + `${ EditSection.selectors.elSection }`
741 + );
742 + const elSections = this.elCurriculumSections.querySelectorAll(
743 + `${ EditSection.selectors.elSection }`
744 + );
745 + const sectionIds = [];
746 +
747 + elSections.forEach( ( elSection ) => {
748 + const sectionId = elSection.dataset.sectionId;
749 + sectionIds.push( sectionId );
750 + } );
751 +
752 + // Call ajax to update section position
753 + const callBack = {
754 + success: ( response ) => {
755 + const { message, status } = response;
756 +
757 + lpToastify.show( message, status );
758 + },
759 + error: ( error ) => {
760 + lpToastify.show( error, 'error' );
761 + },
762 + completed: () => {
763 + lpUtils.lpSetLoadingEl( elSection, 0 );
764 + isUpdateSectionPosition = 0;
765 + },
766 + };
767 +
768 + const dataSend = {
769 + action: 'course_update_section_position',
770 + course_id: this.courseId,
771 + new_position: sectionIds,
772 + args: { id_url: 'course-update-section-position' },
773 + };
774 +
775 + clearTimeout( timeout );
776 + timeout = setTimeout( () => {
777 + lpUtils.lpSetLoadingEl( elSection, 1 );
778 + window.lpAJAXG.fetchAJAX( dataSend, callBack );
779 + }, 1000 );
780 + },
781 + onMove: ( evt ) => {
782 + clearTimeout( timeout );
783 + },
784 + onUpdate: ( evt ) => {
785 + isUpdateSectionPosition = 1;
786 + },
787 + } );
788 + }
789 +
790 + /* Update count sections, when add or delete section */
791 + updateCountSections( elEditCurriculum ) {
792 + const elCountSections = elEditCurriculum.querySelector(
793 + `${ EditSection.selectors.elCountSections }`
794 + );
795 + const elSections = elEditCurriculum.querySelectorAll(
796 + `${ EditSection.selectors.elSection }:not(.clone)`
797 + );
798 + const sectionsCount = elSections.length;
799 +
800 + elCountSections.dataset.count = sectionsCount;
801 + elCountSections.querySelector( '.count' ).textContent = sectionsCount;
802 + }
803 +}