# learnpress/4.3.7/assets/src/js/admin/edit-course/edit-curriculum/edit-section.js

LearnPress – WordPress LMS Plugin for Create and Sell Online Courses, version 4.3.7. 804 lines.

- Page: https://pluginprobe.com/plugins/learnpress/4.3.7/code/assets/src/js/admin/edit-course/edit-curriculum/edit-section.js
- Raw: https://pluginprobe.com/plugins/learnpress/4.3.7/raw/assets/src/js/admin/edit-course/edit-curriculum/edit-section.js
- Modified: 2026-05-23T18:20:54+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/learnpress/4.3.7/code/assets/src/js/admin/edit-course/edit-curriculum/edit-section.js#L10-L20`.

```javascript
/**
 * Edit Section Script on Curriculum
 *
 * @since 4.2.8.6
 * @version 1.0.3
 */
import SweetAlert from 'sweetalert2';
import Sortable from 'sortablejs';
import * as lpUtils from 'lpAssetsJsPath/utils.js';
import * as lpToastify from 'lpAssetsJsPath/lpToastify.js';
import { EditSectionItem } from './edit-section-item.js';
import { EditCourseCurriculum } from '../edit-curriculum.js';

export class EditSection {
	constructor() {
		this.courseId = null;
		this.elEditCurriculum = null;
		this.elCurriculumSections = null;
		this.editSectionItem = new EditSectionItem();
	}

	static selectors = {
		elSection: '.section',
		elDivAddNewSection: '.add-new-section',
		elSectionClone: '.section.clone',
		elSectionTitleNewInput: '.lp-section-title-new-input',
		elSectionTitleInput: '.lp-section-title-input',
		etBtnEditTitle: '.lp-btn-edit-section-title',
		elSectionDesInput: '.lp-section-description-input',
		elBtnAddSection: '.lp-btn-add-section',
		elBtnUpdateTitle: '.lp-btn-update-section-title',
		elBtnUpdateDes: '.lp-btn-update-section-description',
		elBtnCancelUpdateTitle: '.lp-btn-cancel-update-section-title',
		elBtnCancelUpdateDes: '.lp-btn-cancel-update-section-description',
		elBtnDeleteSection: '.lp-btn-delete-section',
		elSectionDesc: '.section-description',
		elSectionToggle: '.section-toggle',
		elCountSections: '.count-sections',
	};

	init() {
		this.elEditCurriculum = document.querySelector(
			`${ EditCourseCurriculum.selectors.idElEditCurriculum }`
		);
		this.elCurriculumSections = this.elEditCurriculum.querySelector(
			`${ EditCourseCurriculum.selectors.elCurriculumSections }`
		);
		const elLPTarget = this.elEditCurriculum.closest(
			`${ EditCourseCurriculum.selectors.LPTarget }`
		);
		const dataSend = window.lpAJAXG.getDataSetCurrent( elLPTarget );
		this.courseId = dataSend.args.course_id;

		this.editSectionItem.init();

		this.events();
		this.sortAbleSection();
	}

	events() {
		// Check and attach events only once
		if ( EditSection._loadedEvents ) {
			return;
		}

		EditSection._loadedEvents = this;

		// Click events
		lpUtils.eventHandlers( 'click', [
			{
				selector: EditSection.selectors.elBtnAddSection,
				class: this,
				callBack: this.addSection.name,
			},
			{
				selector: `${ EditSection.selectors.elBtnUpdateDes }`,
				class: this,
				callBack: this.updateSectionDescription.name,
			},
			{
				selector: `${ EditSection.selectors.etBtnEditTitle }`,
				class: this,
				callBack: this.setFocusTitleInput.name,
			},
			{
				selector: `${ EditSection.selectors.elSectionToggle }`,
				class: this,
				callBack: this.toggleSection.name,
			},
			{
				selector: `${ EditSection.selectors.elBtnCancelUpdateDes }`,
				class: this,
				callBack: this.cancelSectionDescription.name,
			},
			{
				selector: `${ EditSection.selectors.elBtnDeleteSection }`,
				class: this,
				callBack: this.deleteSection.name,
			},
			{
				selector: `${ EditSection.selectors.elBtnUpdateTitle }`,
				class: this,
				callBack: this.updateSectionTitle.name,
			},
			{
				selector: `${ EditSection.selectors.elBtnCancelUpdateTitle }`,
				class: this,
				callBack: this.cancelSectionTitle.name,
			},
			{
				selector: EditCourseCurriculum.selectors.elToggleAllSections,
				class: this,
				callBack: this.toggleSectionAll.name,
			},
		] );

		// Keyup events
		lpUtils.eventHandlers( 'keyup', [
			{
				selector: EditSection.selectors.elSectionTitleNewInput,
				class: this,
				callBack: this.changeTitleBeforeAdd.name,
			},
			{
				selector: EditSection.selectors.elSectionTitleInput,
				class: this,
				callBack: this.changeTitle.name,
			},
			{
				selector: EditSection.selectors.elSectionDesInput,
				class: this,
				callBack: this.changeDescription.name,
			},
		] );

		// Keydown events
		lpUtils.eventHandlers( 'keydown', [
			{
				selector: EditSection.selectors.elSectionTitleNewInput,
				class: this,
				callBack: this.addSection.name,
				checkIsEventEnter: true,
			},
			{
				selector: EditSection.selectors.elSectionDesInput,
				class: this,
				callBack: this.updateSectionDescription.name,
				checkIsEventEnter: true,
			},
			{
				selector: EditSection.selectors.elSectionTitleInput,
				class: this,
				callBack: this.updateSectionTitle.name,
				checkIsEventEnter: true,
			},
		] );

		// Focusin events
		lpUtils.eventHandlers( 'focusin', [
			{
				selector: EditSection.selectors.elSectionTitleNewInput,
				class: this,
				callBack: this.focusTitleNewInput.name,
			},
			{
				selector: EditSection.selectors.elSectionTitleInput,
				class: this,
				callBack: this.focusTitleInput.name,
			},
		] );

		// Focusin events
		lpUtils.eventHandlers( 'focusout', [
			{
				selector: EditSection.selectors.elSectionTitleNewInput,
				class: this,
				callBack: this.focusTitleNewInput.name,
				focusIn: false,
			},
			{
				selector: `${ EditSection.selectors.elSectionTitleInput }`,
				class: this,
				callBack: this.focusTitleInput.name,
				focusIn: false,
			},
		] );
	}

	/* Typing in new section title input */
	changeTitleBeforeAdd( args ) {
		const { e, target } = args;
		const elSectionTitleNewInput = target;

		const elAddNewSection = elSectionTitleNewInput.closest(
			`${ EditSection.selectors.elDivAddNewSection }`
		);
		if ( ! elAddNewSection ) {
			return;
		}

		const elBtnAddSection = elAddNewSection.querySelector(
			`${ EditSection.selectors.elBtnAddSection }`
		);

		const titleValue = elSectionTitleNewInput.value.trim();
		if ( titleValue.length === 0 ) {
			elBtnAddSection.classList.remove( 'active' );
		} else {
			elBtnAddSection.classList.add( 'active' );
		}
	}

	/* Focus on new section title input */
	focusTitleNewInput( args ) {
		const { e, target, focusIn = true } = args;
		const elAddNewSection = target.closest(
			`${ EditSection.selectors.elDivAddNewSection }`
		);
		if ( ! elAddNewSection ) {
			return;
		}

		if ( focusIn ) {
			elAddNewSection.classList.add( 'focus' );
		} else {
			elAddNewSection.classList.remove( 'focus' );
		}
	}

	/* Add new section */
	addSection( args ) {
		const { e, target, callBackNest } = args;

		const elDivAddNewSection = target.closest(
			`${ EditSection.selectors.elDivAddNewSection }`
		);
		if ( ! elDivAddNewSection ) {
			return;
		}

		e.preventDefault();

		const elSectionTitleNewInput = elDivAddNewSection.querySelector(
			`${ EditSection.selectors.elSectionTitleNewInput }`
		);
		const titleValue = elSectionTitleNewInput.value.trim();
		const message = elSectionTitleNewInput.dataset.messEmptyTitle;
		if ( titleValue.length === 0 ) {
			lpToastify.show( message, 'error' );
			return;
		}

		// Clear input after add
		elSectionTitleNewInput.value = '';
		elSectionTitleNewInput.blur();

		// Add and set data for new section
		const elSectionClone = this.elCurriculumSections.querySelector(
			`${ EditSection.selectors.elSectionClone }`
		);
		const newSection = elSectionClone.cloneNode( true );
		newSection.classList.remove( 'clone' );
		lpUtils.lpShowHideEl( newSection, 1 );
		lpUtils.lpSetLoadingEl( newSection, 1 );
		const elSectionTitleInput = newSection.querySelector(
			`${ EditSection.selectors.elSectionTitleInput }`
		);
		elSectionTitleInput.value = titleValue;
		this.elCurriculumSections.insertAdjacentElement(
			'beforeend',
			newSection
		);
		// End

		// Call ajax to add new section
		const callBack = {
			success: ( response ) => {
				const { message, status, data } = response;

				if ( status === 'error' ) {
					newSection.remove();
					throw message;
				} else if ( status === 'success' ) {
					const { section } = data;
					newSection.dataset.sectionId = section.section_id || '';

					// Initialize EditSectionItem for the new section to make its items sortable
					this.editSectionItem.sortAbleItem();

					if (
						callBackNest &&
						typeof callBackNest.success === 'function'
					) {
						args.elSection = newSection;
						args.response = response;
						callBackNest.success( args );
					}
				}

				lpToastify.show( message, status );
			},
			error: ( error ) => {
				newSection.remove();
				lpToastify.show( error, 'error' );
				if (
					callBackNest &&
					typeof callBackNest.error === 'function'
				) {
					args.error = error;
					callBackNest.error( args );
				}
			},
			completed: () => {
				lpUtils.lpSetLoadingEl( newSection, 0 );
				newSection.classList.remove(
					`${ EditCourseCurriculum.selectors.elCollapse }`
				);
				const elSectionDesInput = newSection.querySelector(
					`${ EditSection.selectors.elSectionDesInput }`
				);
				elSectionDesInput.focus();
				this.updateCountSections( this.elEditCurriculum );
				if (
					callBackNest &&
					typeof callBackNest.completed === 'function'
				) {
					args.elSection = newSection;
					callBackNest.completed( args );
				}
			},
		};

		const dataSend = JSON.parse( elSectionTitleNewInput.dataset.send );
		dataSend.section_name = titleValue;
		window.lpAJAXG.fetchAJAX( dataSend, callBack );
	}

	/* Delete section */
	deleteSection( args ) {
		const { e, target } = args;
		const elBtnDeleteSection = target;

		const elEditCurriculum = elBtnDeleteSection.closest(
			`${ EditCourseCurriculum.selectors.idElEditCurriculum }`
		);

		SweetAlert.fire( {
			title: elBtnDeleteSection.dataset.title,
			text: elBtnDeleteSection.dataset.content,
			icon: 'warning',
			showCloseButton: true,
			showCancelButton: true,
			cancelButtonText: lpData.i18n.cancel,
			confirmButtonText: lpData.i18n.yes,
			reverseButtons: true,
		} ).then( ( result ) => {
			if ( result.isConfirmed ) {
				const elSection = elBtnDeleteSection.closest( '.section' );
				const sectionId = elSection.dataset.sectionId;

				lpUtils.lpSetLoadingEl( elSection, 1 );

				// Call ajax to delete section
				const callBack = {
					success: ( response ) => {
						const { message, status } = response;

						lpToastify.show( message, status );
					},
					error: ( error ) => {
						lpToastify.show( error, 'error' );
					},
					completed: () => {
						lpUtils.lpSetLoadingEl( elSection, 0 );
						elSection.remove();
						this.editSectionItem.updateCountItems( elSection );
						this.updateCountSections( elEditCurriculum );
					},
				};

				const dataSend = JSON.parse( elBtnDeleteSection.dataset.send );
				dataSend.section_id = sectionId;
				window.lpAJAXG.fetchAJAX( dataSend, callBack );
			}
		} );
	}

	/* Focus on section title input */
	focusTitleInput( args ) {
		const { e, target, focusIn = true } = args;
		const elSection = target.closest(
			`${ EditSection.selectors.elSection }`
		);
		if ( ! elSection ) {
			return;
		}

		if ( focusIn ) {
			elSection.classList.add( 'focus' );
		} else {
			elSection.classList.remove( 'focus' );
		}
	}

	/* Set focus on section title input */
	setFocusTitleInput( args ) {
		const { e, target } = args;

		const elSection = target.closest(
			`${ EditSection.selectors.elSection }`
		);
		if ( ! elSection ) {
			return;
		}

		const elSectionTitleInput = elSection.querySelector(
			`${ EditSection.selectors.elSectionTitleInput }`
		);
		elSectionTitleInput.setSelectionRange(
			elSectionTitleInput.value.length,
			elSectionTitleInput.value.length
		);
		elSectionTitleInput.focus();
	}

	/* Typing in section title input */
	changeTitle( args ) {
		const { e, target } = args;
		const elSectionTitleInput = target;
		const elSection = elSectionTitleInput.closest(
			`${ EditSection.selectors.elSection }`
		);
		const titleValue = elSectionTitleInput.value.trim();
		const titleValueOld = elSectionTitleInput.dataset.old || '';

		if ( titleValue === titleValueOld ) {
			elSection.classList.remove( 'editing' );
		} else {
			elSection.classList.add( 'editing' );
		}
	}

	/* Update section title to server */
	updateSectionTitle( args ) {
		const { e, target } = args;
		const elSection = target.closest(
			`${ EditSection.selectors.elSection }`
		);
		if ( ! elSection ) {
			return;
		}

		e.preventDefault();

		const elSectionTitleInput = elSection.querySelector(
			`${ EditSection.selectors.elSectionTitleInput }`
		);
		if ( ! elSectionTitleInput ) {
			return;
		}

		const sectionId = elSection.dataset.sectionId;
		const titleValue = elSectionTitleInput.value.trim();
		const titleValueOld = elSectionTitleInput.dataset.old || '';
		const message = elSectionTitleInput.dataset.messEmptyTitle;
		if ( titleValue.length === 0 ) {
			lpToastify.show( message, 'error' );
			return;
		}

		if ( titleValue === titleValueOld ) {
			return;
		}

		elSectionTitleInput.blur();
		lpUtils.lpSetLoadingEl( elSection, 1 );

		// Call ajax to update section title
		const callBack = {
			success: ( response ) => {
				const { message, status } = response;

				lpToastify.show( message, status );

				if ( status === 'success' ) {
					elSectionTitleInput.dataset.old = titleValue;
				}
			},
			error: ( error ) => {
				lpToastify.show( error, 'error' );
			},
			completed: () => {
				lpUtils.lpSetLoadingEl( elSection, 0 );
				elSection.classList.remove( 'editing' );
			},
		};

		const dataSend = JSON.parse( elSectionTitleInput.dataset.send );
		dataSend.section_id = sectionId;
		dataSend.section_name = titleValue;
		window.lpAJAXG.fetchAJAX( dataSend, callBack );
	}

	/* Cancel updating section title */
	cancelSectionTitle( args ) {
		const { e, target } = args;
		const elBtnCancelUpdateTitle = target.closest(
			`${ EditSection.selectors.elBtnCancelUpdateTitle }`
		);
		if ( ! elBtnCancelUpdateTitle ) {
			return;
		}

		const elSection = elBtnCancelUpdateTitle.closest(
			`${ EditSection.selectors.elSection }`
		);
		const elSectionTitleInput = elSection.querySelector(
			`${ EditSection.selectors.elSectionTitleInput }`
		);
		elSectionTitleInput.value = elSectionTitleInput.dataset.old || '';
		elSection.classList.remove( 'editing' );
	}

	/* Update section description to server */
	updateSectionDescription( args ) {
		const { e, target, callBackNest } = args;

		const elSectionDesc = target.closest(
			`${ EditSection.selectors.elSectionDesc }`
		);
		if ( ! elSectionDesc ) {
			return;
		}

		const elSectionDesInput = elSectionDesc.querySelector(
			`${ EditSection.selectors.elSectionDesInput }`
		);
		if ( ! elSectionDesInput ) {
			return;
		}

		e.preventDefault();

		const elSection = elSectionDesInput.closest(
			`${ EditSection.selectors.elSection }`
		);
		const sectionId = elSection.dataset.sectionId;
		const descValue = elSectionDesInput.value.trim();
		const descValueOld = elSectionDesInput.dataset.old || '';

		if ( descValue === descValueOld ) {
			return;
		}

		lpUtils.lpSetLoadingEl( elSection, 1 );

		const callBack = {
			success: ( response ) => {
				const { message, status } = response;

				if (
					callBackNest &&
					typeof callBackNest.success === 'function'
				) {
					args.elSection = elSection;
					args.response = response;
					callBackNest.success( args );
				}

				lpToastify.show( message, status );
			},
			error: ( error ) => {
				lpToastify.show( error, 'error' );
				if (
					callBackNest &&
					typeof callBackNest.error === 'function'
				) {
					callBackNest.error( elSection, error );
				}
			},
			completed: () => {
				lpUtils.lpSetLoadingEl( elSection, 0 );
				const elSectionDesc = elSectionDesInput.closest(
					`${ EditSection.selectors.elSectionDesc }`
				);
				elSectionDesc.classList.remove( 'editing' );
				elSectionDesInput.dataset.old = descValue;
				if (
					callBackNest &&
					typeof callBackNest.completed === 'function'
				) {
					callBackNest.completed( elSection );
				}
			},
		};

		const dataSend = JSON.parse( elSectionDesInput.dataset.send );
		dataSend.section_id = sectionId;
		dataSend.section_description = descValue;
		window.lpAJAXG.fetchAJAX( dataSend, callBack );
	}

	/* Cancel updating section description */
	cancelSectionDescription( args ) {
		const { e, target } = args;
		const elSectionDesc = target.closest(
			`${ EditSection.selectors.elSectionDesc }`
		);
		const elSectionDesInput = elSectionDesc.querySelector(
			`${ EditSection.selectors.elSectionDesInput }`
		);
		elSectionDesInput.value = elSectionDesInput.dataset.old || '';
		elSectionDesc.classList.remove( 'editing' );
	}

	/* Typing in description input */
	changeDescription( ags ) {
		const { e, target } = ags;
		const elSectionDesInput = target.closest(
			`${ EditSection.selectors.elSectionDesInput }`
		);
		if ( ! elSectionDesInput ) {
			return;
		}

		const elSectionDesc = elSectionDesInput.closest(
			`${ EditSection.selectors.elSectionDesc }`
		);
		const descValue = elSectionDesInput.value.trim();
		const descValueOld = elSectionDesInput.dataset.old || '';

		if ( descValue === descValueOld ) {
			elSectionDesc.classList.remove( 'editing' );
		} else {
			elSectionDesc.classList.add( 'editing' );
		}
	}

	toggleSectionAll( args ) {
		const { e, target } = args;
		const elToggleAllSections = target.closest(
			`${ EditCourseCurriculum.selectors.elToggleAllSections }`
		);
		if ( ! elToggleAllSections ) {
			return;
		}

		const elEditCurriculum = elToggleAllSections.closest(
			`${ EditCourseCurriculum.selectors.idElEditCurriculum }`
		);
		const elSections = elEditCurriculum.querySelectorAll(
			`${ EditSection.selectors.elSection }:not(.clone)`
		);

		elToggleAllSections.classList.toggle(
			`${ EditCourseCurriculum.selectors.elCollapse }`
		);

		elSections.forEach( ( el ) => {
			const shouldCollapse = elToggleAllSections.classList.contains(
				`${ EditCourseCurriculum.selectors.elCollapse }`
			);
			el.classList.toggle(
				`${ EditCourseCurriculum.selectors.elCollapse }`,
				shouldCollapse
			);
		} );
	}

	/* Toggle section */
	toggleSection( args ) {
		const { e, target } = args;
		const elSection = target.closest(
			`${ EditSection.selectors.elSection }`
		);

		const elCurriculumSections = elSection.closest(
			`${ EditCourseCurriculum.selectors.elCurriculumSections }`
		);
		if ( ! elCurriculumSections ) {
			return;
		}

		// Toggle section
		elSection.classList.toggle(
			`${ EditCourseCurriculum.selectors.elCollapse }`
		);

		// Check all sections collapsed
		this.checkAllSectionsCollapsed();
	}

	/* Check if all sections are collapsed */
	checkAllSectionsCollapsed() {
		const elSections = this.elEditCurriculum.querySelectorAll(
			`${ EditSection.selectors.elSection }:not(.clone)`
		);
		const elToggleAllSections = this.elEditCurriculum.querySelector(
			`${ EditCourseCurriculum.selectors.elToggleAllSections }`
		);

		let isAllExpand = true;
		elSections.forEach( ( el ) => {
			if (
				el.classList.contains(
					`${ EditCourseCurriculum.selectors.elCollapse }`
				)
			) {
				isAllExpand = false;
				return false; // Break the loop
			}
		} );

		if ( isAllExpand ) {
			elToggleAllSections.classList.remove(
				`${ EditCourseCurriculum.selectors.elCollapse }`
			);
		} else {
			elToggleAllSections.classList.add(
				`${ EditCourseCurriculum.selectors.elCollapse }`
			);
		}
	}

	/* Sortable sections, drag and drop to change section position */
	sortAbleSection() {
		let isUpdateSectionPosition = 0;
		let timeout;

		new Sortable( this.elCurriculumSections, {
			handle: '.drag',
			animation: 150,
			onEnd: ( evt ) => {
				const target = evt.item;
				if ( ! isUpdateSectionPosition ) {
					return;
				}

				const elSection = target.closest(
					`${ EditSection.selectors.elSection }`
				);
				const elSections = this.elCurriculumSections.querySelectorAll(
					`${ EditSection.selectors.elSection }`
				);
				const sectionIds = [];

				elSections.forEach( ( elSection ) => {
					const sectionId = elSection.dataset.sectionId;
					sectionIds.push( sectionId );
				} );

				// Call ajax to update section position
				const callBack = {
					success: ( response ) => {
						const { message, status } = response;

						lpToastify.show( message, status );
					},
					error: ( error ) => {
						lpToastify.show( error, 'error' );
					},
					completed: () => {
						lpUtils.lpSetLoadingEl( elSection, 0 );
						isUpdateSectionPosition = 0;
					},
				};

				const dataSend = {
					action: 'course_update_section_position',
					course_id: this.courseId,
					new_position: sectionIds,
					args: { id_url: 'course-update-section-position' },
				};

				clearTimeout( timeout );
				timeout = setTimeout( () => {
					lpUtils.lpSetLoadingEl( elSection, 1 );
					window.lpAJAXG.fetchAJAX( dataSend, callBack );
				}, 1000 );
			},
			onMove: ( evt ) => {
				clearTimeout( timeout );
			},
			onUpdate: ( evt ) => {
				isUpdateSectionPosition = 1;
			},
		} );
	}

	/* Update count sections, when add or delete section */
	updateCountSections( elEditCurriculum ) {
		const elCountSections = elEditCurriculum.querySelector(
			`${ EditSection.selectors.elCountSections }`
		);
		const elSections = elEditCurriculum.querySelectorAll(
			`${ EditSection.selectors.elSection }:not(.clone)`
		);
		const sectionsCount = elSections.length;

		elCountSections.dataset.count = sectionsCount;
		elCountSections.querySelector( '.count' ).textContent = sectionsCount;
	}
}

```
