let historyStates = []; let currentStateIndex = -1; const $toggleEditModeButton = $('#toggleEditMode'); const $tabBar = $('#tabBar'); const $textOptions = $('#textOptions'); const $imageOptions = $('#imageOptions'); const $BoxOptions = $('#BoxOptions'); const $textColorInput = $('#textColor'); const $textBackgroundInput = $('#textBackground'); const $textContentInput = $('#textContent'); const $imageURLInput = $('#imageURL'); const $imageUploadInput = $('#imageUpload'); const $logoSizeInput = $('#logoSize'); const $sizeValueSpan = $('#sizeValue'); const $lineHeightInput = $('#lineHeight'); let currentElement = null; let isEditMode = false; $(window).scroll(function () { if ($(window).scrollTop() > 100) { $(".mode-edit").addClass('fixed'); } else { $(".mode-edit").removeClass('fixed'); } }) $toggleEditModeButton.on('click', function () { isEditMode = !isEditMode; $('.editable-element').toggleClass('editable', isEditMode); $toggleEditModeButton.html(isEditMode ? ' Thoát chỉnh sửa' : ' Chỉnh sửa'); $tabBar.hide(); }); $imageUploadInput.on('change', function (event) { const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function () { currentElement.find('img').attr('src', reader.result); }; reader.readAsDataURL(file); }); $textColorInput.on('input', function (e) { updateTextColor($(this).val()); }); $textBackgroundInput.on('input', function (e) { updateBackgroundColor($(this).val()); }); $logoSizeInput.on('input', function () { $sizeValueSpan.text(`${$logoSizeInput.val()}px`); currentElement.find('img').css('width', `${$logoSizeInput.val()}px`); }); $lineHeightInput.on('input', function () { if (currentElement && currentElement.data('type') === 'title') { currentElement.find('.title').css('line-height', `${$lineHeightInput.val()}px`); } }); function startEditing(event, button) { if (!isEditMode) return; event.stopPropagation(); currentElement = $(button).closest('.editable-element'); $tabBar.show(); setupOptions(); } function setupOptions() { if (currentElement.data('type') === 'box') { $BoxOptions.show(); $textOptions.hide(); $imageOptions.hide(); const $title = currentElement.find('.title'); $('#BackgroundColor').val(extractColor(currentElement, 'bg')); $('#InputCodeBg').val(extractColor(currentElement, 'bg')); $('#changeInputBg').val(extractColor(currentElement, 'bg')); $textContentInput.val($title.text().trim()); $textColorInput.val(extractColor($title, 'text')); $textBackgroundInput.val(extractColor($title, 'bg')); $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')); $('#borderColorBg').val(extractColor(currentElement, 'border')) } else if (currentElement.data('type') === 'title') { $textOptions.show(); $BoxOptions.hide(); $imageOptions.hide(); const $title = currentElement.find('.title'); $textContentInput.val($title.text().trim()); $textColorInput.val(extractColor($title, 'text')); $textBackgroundInput.val(extractColor($title, 'bg')); $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')); $('#borderColorBg').val(extractColor($title, 'bg')) } else if (currentElement.data('type') === 'background') { } else { $imageOptions.show(); $textOptions.hide(); $BoxOptions.hide(); const $img = currentElement.find('img'); $imageURLInput.attr('src', $img.attr('src')); $imageUploadInput.val(''); const $logoImage = currentElement.find('img'); $logoSizeInput.val($logoImage.width()); $sizeValueSpan.text(`${$logoImage.width()}px`); } } function applyChanges() { if (!currentElement) return; if (currentElement.data('type') === 'title') { updateTextStyles(); } else if (currentElement.data('type') === 'image') { updateImage(); } else if (currentElement.data('type') === 'background') { updateBgStyles() } saveCurrentState() $tabBar.hide(); } function updateTextStyles() { const $title = currentElement.find('h2'); $title.text($textContentInput.val()); updateClass($title, 'text', $textColorInput.val()); updateClass($title, 'bg', $textBackgroundInput.val()); } function updateImage() { const $img = currentElement.find('img'); $img.attr('src', $imageURLInput.val() || $img.attr('src')); } function updateBgStyles() { updateClass(currentElement, 'bg', $('#changeInputBg').val()); updateClass(currentElement, 'bg', $('#InputCodeBg').val()); } function updateTextColor(color) { if (!currentElement) return; updateClass(currentElement.find('h2'), 'text', color); } function updateBackgroundColor(color) { if (!currentElement) return; updateClass(currentElement.find('h2'), 'bg', color); } function updateClass($element, type, color) { const className = type === 'text' ? `text-[${color}]` : `bg-[${color}]`; const regex = new RegExp(`^${type}-\\[#[0-9A-Fa-f]{3,6}\\]$`); $element.attr('class', function (i, c) { return c.split(' ').filter(cls => !regex.test(cls)).concat(className).join(' '); }); } function extractColor($element, type) { const regex = new RegExp(`${type}-\\[([#0-9A-Fa-f]+)\\]`); const match = $element.attr('class').match(regex); return match ? match[1] : '#000000'; } function formatText(command, value) { let $title = ''; if (currentElement.data('type') === 'title' || currentElement.data('type') == 'box') { $title = currentElement.find('.title'); } else { $title = currentElement; } switch (command) { case 'size': $title.css('font-size', `${value}px`); break; case 'bold': $title.toggleClass('font-bold'); break; case 'italic': $title.toggleClass('italic'); break; case 'underline': $title.toggleClass('underline'); break; case 'line-through': $title.toggleClass('line-through'); break; case 'justifyLeft': $title.removeClass('text-center text-right text-justify').addClass('text-left'); break; case 'justifyCenter': $title.removeClass('text-left text-right text-justify').addClass('text-center'); break; case 'justifyRight': $title.removeClass('text-left text-center text-justify').addClass('text-right'); break; case 'justifyFull': $title.removeClass('text-left text-center text-right').addClass('text-justify'); break; } } function updateColorPicker(event, type) { const textColor = $("#textColor"); const textCodeColor = $("#colorCodeTitle"); const BgColor = $("#textBackground"); let element = ''; if (currentElement.data('type') === 'title') { element = currentElement.find('.title'); } else { element = currentElement; } if (type === 'text') { const isValidHex = /^#([0-9A-F]{3}){1,2}$/i.test(textCodeColor.val()); if (isValidHex) { textColor.val(textCodeColor.val()); element.css('color', textCodeColor.val()); } else { alert("Vui lòng nhập mã màu hợp lệ (ví dụ: #FF5733)."); } } else if (type === 'background') { const isValidHex = /^#([0-9A-F]{3}){1,2}$/i.test($(event.target).val()); if (isValidHex) { BgColor.val($(event.target).val()); element.css('background', $(event.target).val()); } else { alert("Vui lòng nhập mã màu hợp lệ (ví dụ: #FF5733)."); } } } function syncColorInputs(event, type) { const inputColorText = $('#colorCodeTitle'); let inputBg = ''; let Bg = ''; if (currentElement.data('type') === 'title') { inputBg = $('#BgcolorCode'); bg = $(currentElement).find('.title'); } else { inputBg = $('#InputCodeBg'); bg = $(currentElement); } if (type == 'text') { inputColorText.val($(event.target).val()); } else { inputBg.val($(event.target).val()); bg.css('background', $(event.target).val()); } } function updatePosition(event, action) { $('.edit-position').removeClass('active') $(event.target).addClass('active'); console.log(action) if (action == 'left') { currentElement.find('.title').css({ 'margin': 'auto auto auto 0', 'justify-content': 'start' }); } else if (action == 'center') { currentElement.find('.title').css({ 'margin': '0 auto', 'justify-content': 'center' }); } else if (action == 'right') { console.log('aaa', currentElement) currentElement.find('.title').css({ 'margin': 'auto 0 auto auto', 'justify-content': 'end' }); } } function updateSizeBox(type, value) { if (type == 'width') { currentElement.find('.title').css('width', value + 'px') } else if (type == 'height') { currentElement.find('.title').css('height', value + 'px') } } function updateBoderRadius(type, key, value) { let element = ''; if (key == 'background') { element = currentElement; } else if (key == 'text') { element = currentElement.find('.title'); } if (type == 'top-left') { element.css('border-top-left-radius', value + 'px'); } else if (type == 'top-right') { element.css('border-top-right-radius', value + 'px'); } else if (type == 'bottom-left') { element.css('border-bottom-left-radius', value + 'px'); } else if (type == 'bottom-right') { element.css('border-bottom-right-radius', value + 'px'); } } function updateBorder(type, key, value) { let element = ''; if (key == 'background') { element = currentElement; } else if (key == 'text') { element = currentElement.find('.title'); } if (type == 'border-width') { element.css('border-width', value + 'px'); } else if (type == 'border-color') { element.css('border-color', value); } else if (type == 'border-style') { element.css('border-style', value); } } function saveCurrentState() { // Lưu HTML hiện tại của giao diện const currentHTML = document.documentElement.innerHTML; // Nếu không ở cuối mảng (khi đã dùng nút back hoặc forward), loại bỏ các trạng thái phía sau if (currentStateIndex < historyStates.length - 1) { historyStates = historyStates.slice(0, currentStateIndex + 1); } // Lưu trạng thái mới và cập nhật chỉ số trạng thái hiện tại historyStates.push(currentHTML); currentStateIndex++; } function goBack() { if (currentStateIndex > 0) { currentStateIndex--; document.documentElement.innerHTML = historyStates[currentStateIndex]; } } function goForward() { if (currentStateIndex < historyStates.length - 1) { currentStateIndex++; document.documentElement.innerHTML = historyStates[currentStateIndex]; } }