import $ from 'jquery'; // Khai báo các biến trạng thái chính để quản lý lịch sử các trạng thái giao diện let historyStates: string[] = []; // Lưu trữ lịch sử HTML của trang let currentStateIndex: number = -1; // Chỉ số trạng thái hiện tại trong lịch sử let currentElement: JQuery | null = null; // Phần tử hiện đang chỉnh sửa let isEditMode: boolean = false; // Xác định chế độ chỉnh sửa có được bật không // Định nghĩa kiểu dữ liệu cho phần tử giao diện interface Elements { toggleEditModeButton: JQuery; tabBar: JQuery; textOptions: JQuery; imageOptions: JQuery; boxOptions: JQuery; bgOptions: JQuery; textColorInput: JQuery; textBackgroundInput: JQuery; textContentInput: JQuery; imageURLInput: JQuery; imageUploadInput: JQuery; logoSizeInput: JQuery; sizeValueSpan: JQuery; lineHeightInput: JQuery; } // Các phần tử giao diện được chọn từ DOM, chứa các thành phần tương tác trong giao diện chỉnh sửa const $elements: Elements = { // Nút để bật hoặc tắt chế độ chỉnh sửa toggleEditModeButton: $('#toggleEditMode'), // Thanh công cụ hiển thị các tùy chọn khi chỉnh sửa phần tử tabBar: $('#tabBar'), // Phần tùy chọn cho chỉnh sửa văn bản, bao gồm các thiết lập màu, nội dung và khoảng cách dòng textOptions: $('#textOptions'), // Phần tùy chọn cho chỉnh sửa ảnh, bao gồm URL ảnh và kích thước imageOptions: $('#imageOptions'), // Phần tùy chọn cho chỉnh sửa hộp (box), có thể dùng để thay đổi kích thước hoặc màu nền boxOptions: $('#BoxOptions'), // Phần tùy chọn cho chỉnh sửa nền, cho phép thiết lập màu nền bgOptions: $('#bgOptions'), // Trường nhập liệu cho màu chữ, cho phép người dùng chọn màu chữ của tiêu đề hoặc văn bản textColorInput: $('#textColor'), // Trường nhập liệu cho màu nền của văn bản, cho phép người dùng thay đổi màu nền của tiêu đề textBackgroundInput: $('#textBackground'), // Trường nhập liệu cho nội dung văn bản, dùng để chỉnh sửa nội dung của tiêu đề textContentInput: $('#textContent'), // Trường nhập liệu URL của ảnh, cho phép người dùng nhập URL để thay đổi ảnh imageURLInput: $('#imageURL'), // Trường tải lên ảnh, cho phép người dùng tải ảnh trực tiếp từ máy tính imageUploadInput: $('#imageUpload'), // Trường nhập liệu cho kích thước logo, dùng để điều chỉnh kích thước ảnh hoặc logo logoSizeInput: $('#logoSize'), // Hiển thị giá trị kích thước hiện tại của ảnh, được cập nhật khi thay đổi kích thước logo sizeValueSpan: $('#sizeValue'), // Trường nhập liệu khoảng cách dòng, giúp người dùng điều chỉnh khoảng cách dòng của văn bản lineHeightInput: $('#lineHeight') }; // Lắng nghe sự kiện scroll để chuyển chế độ cố định cho thanh công cụ khi cuộn xuống $(window).scroll((): void => { const scrollTop: number = $(window).scrollTop() ?? 0; $(".mode-edit").toggleClass('fixed', scrollTop > 100); }); /** * Bật/tắt chế độ chỉnh sửa. * Khi bật, các phần tử sẽ có thể chỉnh sửa, và ngược lại. */ $elements.toggleEditModeButton.on('click', function () { isEditMode = !isEditMode; $('.editable-element').toggleClass('editable', isEditMode); $elements.toggleEditModeButton.html(isEditMode ? ' Thoát chỉnh sửa' : ' Chỉnh sửa'); $elements.tabBar.hide(); }); /** * Cập nhật màu sắc của phần tử hiện tại. * @param type - Loại màu sắc cần thay đổi ('text' hoặc 'bg'). * @param color - Mã màu cần áp dụng cho phần tử. */ function updateElementColor(type: 'text' | 'bg', color: string): void { if (!currentElement) return; const className = type === 'text' ? `text-[${color}]` : `bg-[${color}]`; currentElement.find('.title').attr('class', function (i, c) { return c ? c.split(' ').filter(cls => !cls.startsWith(type)).concat(className).join(' ') : className; }); } /** * Xử lý tải ảnh lên và gán ảnh mới cho phần tử. * @param event - Sự kiện thay đổi từ ô tải ảnh lên. */ function handleImageUpload(event: JQuery.ChangeEvent): void { const file = (event.target as HTMLInputElement).files?.[0]; if (!file) return; const reader = new FileReader(); reader.onload = function () { currentElement?.find('img').attr('src', reader.result as string); }; reader.readAsDataURL(file); } /** * Bắt đầu chế độ chỉnh sửa cho phần tử được chọn. * @param event - Sự kiện click để bắt đầu chỉnh sửa. * @param button - Nút bấm để kích hoạt chỉnh sửa phần tử. */ function startEditing(event: JQuery.ClickEvent, button: HTMLElement): void { if (!isEditMode) return; event.stopPropagation(); currentElement = $(button).closest('.editable-element'); $elements.tabBar.show(); setupOptions(); } /** * Thiết lập các tùy chọn cho phần tử đang chỉnh sửa dựa trên loại của nó. */ function setupOptions(): void { if (!currentElement) return; const elementType = currentElement.data('type') as string; if (elementType === 'box') { showBoxOptions(currentElement); } else if (elementType === 'title') { showTextOptions(currentElement.find('.title')); } else if (elementType === 'background') { showBgOptions(); } else if (elementType === 'image') { showImageOptions(); } } // Các hàm hiển thị và xử lý tùy chọn (showTextOptions, showBgOptions, showImageOptions, showBoxOptions) // Thêm vào TypeScript, định nghĩa tham số và chú thích /** * Hiển thị các tùy chọn văn bản cho phần tử tiêu đề. * @param $title - Phần tử tiêu đề hiện tại. */ function showTextOptions($title: JQuery): void { // Hiển thị các tùy chọn và thiết lập giá trị hiện tại cho ô input $elements.textOptions.show(); $elements.boxOptions.hide(); $elements.imageOptions.hide(); $elements.bgOptions.hide(); $elements.textContentInput.val($title.text().trim()); $elements.textColorInput.val(extractColor($title, 'text')); $elements.textBackgroundInput.val(extractColor($title, 'bg')); $elements.lineHeightInput.val(parseFloat($title.css('line-height'))); $('#fontSize').val(parseFloat($title.css('font-size'))); $('#fontFamily').val($title.css('font-family')); $('#BgcolorCode').val(extractColor($title, 'bg')); $('#colorCodeTitle').val(extractColor($title, 'text')); } /** * Trích xuất mã màu từ lớp CSS của phần tử. * @param $element - Phần tử để lấy mã màu. * @param type - Loại mã màu ('text' hoặc 'bg'). * @returns Mã màu đã được trích xuất hoặc '#000000' nếu không có. */ function extractColor($element: JQuery, type: 'text' | 'bg'): string { const regex = new RegExp(`${type}-\\[([#0-9A-Fa-f]+)\\]`); const match = $element.attr('class')?.match(regex); return match ? match[1] : '#000000'; } /** * Lưu trạng thái hiện tại vào lịch sử trạng thái. */ function saveCurrentState(): void { const currentHTML = document.documentElement.innerHTML; if (currentStateIndex < historyStates.length - 1) { historyStates = historyStates.slice(0, currentStateIndex + 1); } historyStates.push(currentHTML); currentStateIndex++; } // hàm xử lý chỉnh sửa box function showBoxOptions(currentElement: JQuery): void { // Đảm bảo $elements có kiểu chính xác // .show() và .hide() trả về đối tượng jQuery, nên không cần lưu giá trị trả về $elements.boxOptions.show(); $elements.textOptions.hide(); $elements.imageOptions.hide(); // Lấy phần tử có class 'title' từ currentElement, với kiểu JQuery const $title: JQuery = currentElement.find('.title'); // Sử dụng phương thức extractColor để lấy màu nền, và gán giá trị vào các input // Giả sử extractColor trả về kiểu string hoặc null $('#BackgroundColor').val(extractColor(currentElement, 'bg') ?? ''); // Gán giá trị mặc định nếu null $('#InputCodeBox').val(extractColor(currentElement, 'bg') ?? ''); $('#changeInputBox').val(extractColor(currentElement, 'bg') ?? ''); // Lấy và gán giá trị text của title vào input textContentInput // .text() trả về string $elements.textContentInput.val($title.text().trim()); // Lấy màu sắc văn bản từ title và gán vào các input tương ứng $elements.textColorInput.val(extractColor($title, 'text') ?? ''); $elements.textBackgroundInput.val(extractColor($title, 'bg') ?? ''); // Lấy chiều cao dòng (line-height) của title, và ép kiểu sang float $elements.lineHeightInput.val(parseFloat($title.css('line-height') ?? '0')); // Lấy kích thước font của title, ép kiểu sang float $('#fontSize').val(parseFloat($title.css('font-size') ?? '0')); // Lấy font-family của title và gán vào input fontFamily $('#fontFamily').val($title.css('font-family') ?? ''); // Gán màu nền của title vào input BgcolorCode const a: string | undefined = $('#BgcolorCode').val(extractColor($title, 'bg') ?? '') as string; console.log(a); // In ra giá trị lấy từ extractColor // Gán màu sắc của title vào input colorCodeTitle $('#colorCodeTitle').val(extractColor($title, 'text') ?? ''); // Gán màu biên của currentElement vào input borderColorBox $('#borderColorBox').val(extractColor(currentElement, 'border') ?? ''); }