lồng nhau (bên trong) hay không
const memberID = 0;
const vbID = '0a61cc6483d561ad9037127021f63416';
// State management cho phân tích
let isAnalyzing = false; // Có đang phân tích không
let currentAnalyzingAddress = null; // Address đang được phân tích
let currentAnalyzingElement = null; // Element đang được phân tích
let currentAnalyzingBadge = null; // Badge của element đang phân tích
console.log('Tiện ích loaded - memberID:', memberID, 'vbID:', vbID);
function isInViewportAndTabNoiDung(element) {
const rect = element.getBoundingClientRect();
const buffer = 1500; // Buffer to preload content below the viewport (approx. 50+ lines)
const viewHeight = window.innerHeight || document.documentElement.clientHeight;
const isInViewport = rect.top < viewHeight + buffer && rect.bottom >= 0;
const isInTabNoiDung = $(element).closest('#tab_noi_dung_vb').length > 0;
return isInViewport && isInTabNoiDung;
}
function getAddress(element) {
const validTags = ['trichyeu', 'cancu', 'phan', 'chuong', 'muc', 'tieumuc', 'dieu', 'khoan', 'diem'];
const $parent = $(element).closest(validTags.join(','));
if (!$parent.length) {
return null;
}
let addr = $parent.attr('address');
if (!addr && $parent.prop('tagName').toLowerCase() === 'trichyeu') {
addr = 'trichyeu';
$parent.attr('address', addr);
}
return addr || null;
}
function processTnplClasses($element) {
const tnplKeysInLine = new Set(); // key = slug hoặc text (thường là slug)
$element.find('tnpl').each(function () {
const $tnpl = $(this);
const tnplSlug = ($tnpl.attr('slug') || '').trim().toLowerCase();
const tnplKey = tnplSlug || $tnpl.text().trim().toLowerCase();
// Đã xử lý trong cùng dòng => bỏ
if (tnplKeysInLine.has(tnplKey)) {
return;
}
tnplKeysInLine.add(tnplKey);
let tnplExists = false;
// Chỉ duyệt các tnpl đã được tô màu (class on)
$('tnpl.on').each(function () {
const $existingTnpl = $(this);
const existingSlug = ($existingTnpl.attr('slug') || '').trim().toLowerCase();
const existingKey = existingSlug || $existingTnpl.text().trim().toLowerCase();
if (
existingKey === tnplKey &&
isInViewportAndTabNoiDung($existingTnpl[0])
) {
tnplExists = true;
return false; // break each
}
});
if (!tnplExists) {
$tnpl.addClass('on');
}
});
}
function processQueue() {
while (pendingRequests < maxConcurrentRequests && requestQueue.length > 0) {
const task = requestQueue.shift();
pendingRequests++;
task()
.always(() => {
pendingRequests--;
processQueue();
});
}
}
function processVisibleParagraphs() {
try {
$('#tab_noi_dung_vb p:not([is-posted="1"])').each(function () {
let $element = $(this);
if (isInViewportAndTabNoiDung(this)) {
$element.attr('is-posted', '1');
$element.addClass('loading-content');
let p_innerHTML = $element.html();
let address = null;
if (cac_cau_hinh.loai_noi_dung.includes('docs')) {
address = getAddress($element);
}
const isSubP = $element.parents('p').length > 0;
if (isSubP && !allow_sub_p) {
$element.removeClass('loading-content');
return; // Không gửi nếu không cho phép
}
const postData = { p_content: p_innerHTML, cac_cau_hinh, address };
if (isSubP && allow_sub_p) {
postData.sub_p = 1;
}
requestQueue.push(() =>
$.ajax({
url: '//tnpl' + (Math.floor(Math.random() * 10) + 1) + '.hethongphapluat.com/tien-ich/tim.tien.ich.php',
type: 'POST',
data: postData,
success: function(response) {
$element.html(response);
processTnplClasses($element);
// Đợi CTTD và các tiện ích load xong rồi mới attach badge
if (memberID === 4 && typeof attachPhanTichBadge === 'function') {
setTimeout(function() {
// $element chính là thẻ p, kiểm tra và attach badge trực tiếp
const $parent = $element.closest('phan, chuong, muc, tieumuc, dieu, khoan, diem');
if ($parent.length > 0 && $parent.find('.badge-phan-tich[data-for="' + $parent.attr('address') + '"]').length === 0) {
const address = $parent.attr('address');
$element.attr('data-address', address);
// Lấy tên loại thẻ cho tooltip
const parentType = getParentTypeName($parent.prop('tagName').toLowerCase());
// Append badge VÀO PARENT (dieu, khoan,...) thay vì vào để tránh xung đột CTTD
const $badge = $('Phân tích');
$parent.append($badge);
// Thêm class để CSS set position: relative CHỈ cho element có badge
$parent.addClass('has-phan-tich-badge');
}
// Xử lý các p con (nếu có sub-p)
attachPhanTichBadge($element);
}, 300); // Đợi 300ms để CTTD render xong
}
},
complete: function() {
$element.removeClass('loading-content');
}
})
);
processQueue();
}
});
} catch(e) {
console.error('Lỗi processVisibleParagraphs:', e);
}
}
$(window).on('scroll resize', function () {
processVisibleParagraphs();
});
console.log('Bắt đầu processVisibleParagraphs lần đầu...');
processVisibleParagraphs();
console.log('processVisibleParagraphs lần đầu hoàn thành');
// Chức năng phân tích điều luật (chỉ cho member_id = 4)
if (memberID === 4) {
// Modal cảnh báo
function showWarningModal(message) {
// Tạo modal nếu chưa có
if ($('#warningModal').length === 0) {
const modalHTML = `
`;
$('body').append(modalHTML);
}
$('#warningModalBody').html('' + message + '
');
$('#warningModal').modal('show');
}
// Hàm lấy tên tiếng Việt của thẻ
function getParentTypeName(tagName) {
const typeNames = {
'phan': 'Phần',
'chuong': 'Chương',
'muc': 'Mục',
'tieumuc': 'Tiểu mục',
'dieu': 'Điều',
'khoan': 'Khoản',
'diem': 'Điểm'
};
return typeNames[tagName] || 'Nội dung';
}
function attachPhanTichBadge($container) {
const validTags = 'phan, chuong, muc, tieumuc, dieu, khoan, diem';
$container.find('p').each(function() {
const $p = $(this);
const $parent = $p.closest(validTags);
if ($parent.length > 0) {
const address = $parent.attr('address');
// Kiểm tra đã có badge cho parent này chưa
if ($parent.find('.badge-phan-tich[data-for="' + address + '"]').length === 0) {
// Lưu address vào data attribute
$p.attr('data-address', address);
// Lấy tên loại thẻ cho tooltip
const parentType = getParentTypeName($parent.prop('tagName').toLowerCase());
// Append badge vào PARENT, không vào
const $badge = $('Phân tích');
$parent.append($badge);
// Thêm class để CSS set position: relative CHỈ cho element có badge
$parent.addClass('has-phan-tich-badge');
}
}
});
}
// Helper: Escape HTML entities
function escapeHtml(text) {
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return String(text).replace(/[&<>"']/g, function(m) { return map[m]; });
}
// Helper: Convert Markdown to HTML (đơn giản)
function markdownToHtml(markdown) {
if (!markdown) return '';
let html = markdown;
// Headers
html = html.replace(/^### (.*$)/gim, '
$1
');
html = html.replace(/^## (.*$)/gim, '$1
');
html = html.replace(/^# (.*$)/gim, '$1
');
// Bold
html = html.replace(/\*\*(.*?)\*\*/g, '$1');
// Italic
html = html.replace(/\*(.*?)\*/g, '$1');
// Blockquote
html = html.replace(/^> (.*$)/gim, '$1
');
html = html.replace(/^> (.*$)/gim, '$1
');
// Lists (unordered)
html = html.replace(/^\- (.*$)/gim, '$1');
html = html.replace(/(.*<\/li>)/s, '');
// Lists (ordered)
html = html.replace(/^\d+\. (.*$)/gim, '$1');
// Line breaks và paragraphs
html = html.split('\n\n').map(para => {
para = para.trim();
if (para.startsWith('')) {
return para;
}
if (para) {
return '' + para.replace(/\n/g, '
') + '
';
}
return '';
}).join('\n');
// Clean up multiple line breaks
html = html.replace(/\n{3,}/g, '\n\n');
return html;
}
// Panel trượt đè lên #rightdocinfo để hiển thị phân tích điều luật
function closePhanTichPanel() {
const $panel = $('#phanTichPanel');
if ($panel.length) {
$panel.removeClass('show');
setTimeout(() => $panel.remove(), 300);
}
// Reset highlight và badge khi đóng panel
if (currentAnalyzingElement) {
currentAnalyzingElement.removeClass('highlight-border-persistent');
}
if (currentAnalyzingBadge) {
currentAnalyzingBadge.text('Phân tích').removeClass('analyzing');
currentAnalyzingBadge.data('analyzing', false);
currentAnalyzingBadge.data('hovering', false);
currentAnalyzingBadge.css({display: 'none'}); // Ẩn badge khi đóng
}
// Reset tất cả các element khác (trong trường hợp có nhiều)
$('#tab_noi_dung_vb .highlight-border-persistent').removeClass('highlight-border-persistent');
$('#tab_noi_dung_vb .badge-phan-tich-container.analyzing').each(function() {
$(this).text('Phân tích').removeClass('analyzing').data('analyzing', false);
});
// Reset state
isAnalyzing = false;
currentAnalyzingAddress = null;
currentAnalyzingElement = null;
currentAnalyzingBadge = null;
}
function openPhanTichPanel(address, vbID) {
console.log('openPhanTichPanel called with address:', address);
console.log('Current state - isAnalyzing:', isAnalyzing, 'currentAnalyzingAddress:', currentAnalyzingAddress);
// Kiểm tra nếu đang phân tích element khác
if (isAnalyzing && currentAnalyzingAddress && currentAnalyzingAddress !== address) {
const currentName = getElementDisplayName(currentAnalyzingAddress);
console.warn('Already analyzing:', currentAnalyzingAddress, 'Cannot analyze:', address);
showWarningModal('Vui lòng chờ phân tích ' + currentName + ' hoàn tất...');
return;
}
// Nếu đang phân tích cùng element → không làm gì
if (isAnalyzing && currentAnalyzingAddress === address) {
console.log('Already analyzing this element, ignoring duplicate request');
return;
}
// ĐÓNG tất cả CTTD pointer đang mở để tránh xung đột z-index
const $cttdPointers = $('.pointer.pointy.zindex');
const $cttdCanvas = $('canvas.pointy.zindex');
if ($cttdPointers.length > 0 || $cttdCanvas.length > 0) {
console.log('Found CTTD pointers:', $cttdPointers.length, 'canvas:', $cttdCanvas.length, '- closing...');
$('.close_pointy').trigger('click');
// Đóng trực tiếp nếu còn
$cttdPointers.fadeOut(200, function() { $(this).remove(); });
$cttdCanvas.fadeOut(200, function() { $(this).remove(); });
console.log('CTTD pointers and canvas removed');
}
const $container = $('#rightdocinfo');
if ($container.length === 0) {
// Fallback: nếu không có rightdocinfo, dùng modal cũ
return openPhanTichModal(address, vbID);
}
// XÓA highlight persistent của TẤT CẢ elements cũ trước
$('#tab_noi_dung_vb .highlight-border-persistent').removeClass('highlight-border-persistent');
console.log('Removed all previous highlight-border-persistent');
// Tìm element đang được phân tích và badge của nó
const $element = $('[address="' + address + '"]');
const $badge = $element.find('.badge-phan-tich-container[data-for="' + address + '"]').first();
// Set state
isAnalyzing = true;
currentAnalyzingAddress = address;
currentAnalyzingElement = $element;
currentAnalyzingBadge = $badge;
console.log('State set:', {
isAnalyzing: isAnalyzing,
currentAnalyzingAddress: currentAnalyzingAddress,
elementFound: $element.length > 0,
badgeFound: $badge.length > 0
});
// Thêm highlight persistent cho element MỚI này
$element.addClass('highlight-border-persistent');
// Thay đổi badge thành "Đang phân tích..." và giữ hiển thị
if ($badge.length > 0) {
$badge.text('Đang phân tích...').addClass('analyzing');
// Giữ badge hiển thị và ở đúng vị trí
$badge.data('analyzing', true);
$badge.data('hovering', true); // Prevent auto-hide
console.log('Badge set to analyzing state');
// Đảm bảo badge hiển thị ở đúng vị trí (vì dùng position: fixed)
showPhanTichBadgeForParent($element);
}
// Tạo panel nếu chưa có
if ($('#phanTichPanel').length === 0) {
const panelHTML = `
Đang phân tích...
Đang phân tích...
`;
// Đảm bảo container có position relative
if ($container.css('position') === 'static') {
$container.css('position', 'relative');
}
$container.append(panelHTML);
// Trigger slide-in với force z-index
setTimeout(() => {
const $panel = $('#phanTichPanel');
$panel.addClass('show');
$panel.css('z-index', '10001'); // Force z-index
console.log('Panel created and shown with z-index:', $panel.css('z-index'));
}, 10);
} else {
$('#phanTichPanelBody').html(`
Đang phân tích...
Đang phân tích...
`);
const $panel = $('#phanTichPanel');
$panel.addClass('show');
$panel.css('z-index', '10001'); // Force z-index
console.log('Panel re-shown with z-index:', $panel.css('z-index'));
}
// Bind nút đóng và ESC
$(document).off('click.closePhanTich').on('click.closePhanTich', '.close-phan-tich', function() {
closePhanTichPanel();
});
$(document).off('keyup.closePhanTich').on('keyup.closePhanTich', function(e) {
if (e.key === 'Escape') closePhanTichPanel();
});
// Gọi API phân tích
const randomServer = Math.floor(Math.random() * 10) + 1;
$.ajax({
url: '//tnpl' + randomServer + '.hethongphapluat.com/tien-ich/phan.tich.dieu.luat.php',
type: 'POST',
contentType: 'application/json',
timeout: 300000, // 5 phút
data: JSON.stringify({
address: address,
vb_id: vbID
}),
success: function(response) {
console.log('Analysis complete for:', address, response);
// Reset badge về trạng thái bình thường (nhưng vẫn hiển thị)
if (currentAnalyzingBadge) {
currentAnalyzingBadge.text('Phân tích').removeClass('analyzing');
currentAnalyzingBadge.data('analyzing', false);
console.log('Badge reset to normal state');
}
// Reset state analyzing để có thể phân tích element khác
isAnalyzing = false;
console.log('State reset: isAnalyzing = false, can analyze other elements now');
if (response.ok) {
// Render kết quả phân tích
let html = '';
html += '';
html += '
' + escapeHtml(response.ten_van_ban) + '
';
if (response.so_hieu) {
html += 'Số hiệu: ' + escapeHtml(response.so_hieu) + '
';
}
html += 'Điều khoản: ' + escapeHtml(response.address) + '';
html += '';
html += '' + markdownToHtml(response.phan_tich) + '
';
if (response.usage) {
html += '';
html += 'Thống kê: ';
html += 'Input tokens: ' + (response.usage.promptTokenCount || 0) + ', ';
html += 'Output tokens: ' + (response.usage.candidatesTokenCount || 0);
html += '
';
}
$('#phanTichPanelBody').html(html);
} else {
$('#phanTichPanelBody').html(`
Lỗi! ${escapeHtml(response.error || 'Không thể phân tích điều luật.')}
Vui lòng thử lại sau.
`);
}
},
error: function(xhr, status, error) {
console.error('Analysis error:', error);
// Reset badge về trạng thái bình thường
if (currentAnalyzingBadge) {
currentAnalyzingBadge.text('Phân tích').removeClass('analyzing');
currentAnalyzingBadge.data('analyzing', false);
}
// Reset state analyzing
isAnalyzing = false;
let errorMsg = error;
if (xhr.responseJSON && xhr.responseJSON.error) {
errorMsg = xhr.responseJSON.error;
}
$('#phanTichPanelBody').html(`
Lỗi! Không thể kết nối đến server phân tích.
Chi tiết: ${escapeHtml(errorMsg)}
`);
}
});
}
// Helper: Lấy tên hiển thị của element từ address
function getElementDisplayName(address) {
if (!address) return 'nội dung';
const $element = $('[address="' + address + '"]');
if ($element.length === 0) return address;
const tagName = $element.prop('tagName').toLowerCase();
const parentType = getParentTypeName(tagName);
// Lấy số thứ tự từ address
let displayText = parentType;
// Parse address: vd "khoan_3_dieu_4" -> "Khoản 3 Điều 4"
const parts = address.split('_');
for (let i = 0; i < parts.length; i += 2) {
if (i + 1 < parts.length) {
const type = getParentTypeName(parts[i]);
const num = parts[i + 1];
displayText = type + ' ' + num;
}
}
return displayText;
}
function openPhanTichModal(address, vbID) {
// Tạo modal nếu chưa có
if ($('#modalPhanTich').length === 0) {
const modalHTML = `
Đang phân tích...
Đang phân tích...
`;
$('body').append(modalHTML);
}
// Reset và hiển thị modal với loading
$('#modalPhanTichBody').html(`
Đang phân tích...
Đang phân tích...
`);
$('#modalPhanTich').modal('show');
// AJAX request
const randomServer = Math.floor(Math.random() * 10) + 1;
$.ajax({
url: '//tnpl' + randomServer + '.hethongphapluat.com/tien-ich/phan.tich.dieu.luat.php',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({
address: address,
vb_id: vbID
}),
success: function(response) {
if (response.ok) {
// Render kết quả phân tích
let html = '';
// Header thông tin văn bản
html += '';
html += '
' + escapeHtml(response.ten_van_ban) + '
';
if (response.so_hieu) {
html += 'Số hiệu: ' + escapeHtml(response.so_hieu) + '
';
}
html += 'Điều khoản: ' + escapeHtml(response.address) + '';
html += '';
// Nội dung phân tích (Markdown -> HTML)
html += '';
html += markdownToHtml(response.phan_tich);
html += '
';
// Thông tin usage (nếu có)
if (response.usage) {
html += '';
html += 'Thống kê: ';
html += 'Input tokens: ' + (response.usage.promptTokenCount || 0) + ', ';
html += 'Output tokens: ' + (response.usage.candidatesTokenCount || 0);
html += '
';
}
$('#modalPhanTichBody').html(html);
} else {
$('#modalPhanTichBody').html(`
Lỗi! ${escapeHtml(response.error || 'Không thể phân tích điều luật.')}
Vui lòng thử lại sau.
`);
}
},
error: function(xhr, status, error) {
let errorMsg = error;
if (xhr.responseJSON && xhr.responseJSON.error) {
errorMsg = xhr.responseJSON.error;
}
$('#modalPhanTichBody').html(`
Lỗi! Không thể kết nối đến server phân tích.
Chi tiết: ${escapeHtml(errorMsg)}
`);
}
});
}
// Helpers: show/hide badge cho parent element (dieu, khoan,...) với position: fixed
function showPhanTichBadgeForParent($parent) {
// Lấy badge CỦA CHÍNH parent này (match data-for với address của parent)
const parentAddress = $parent.attr('address');
const $badge = $parent.find('.badge-phan-tich-container[data-for="' + parentAddress + '"]').first();
if ($badge.length === 0) {
console.warn('No badge found for parent:', parentAddress);
return;
}
// Ẩn TẤT CẢ các badge khác để tránh overlap
$('.badge-phan-tich-container').not($badge).each(function() {
const $otherBadge = $(this);
// Chỉ ẩn badge KHÔNG đang analyzing
if (!$otherBadge.data('analyzing')) {
$otherBadge.css({display: 'none'});
}
});
// Show badge tạm để tính width
$badge.css({display: 'inline-block', opacity: 0, visibility: 'hidden'});
const badgeWidth = $badge.outerWidth();
// Tính toán vị trí fixed dựa trên offset của parent
const offset = $parent.offset();
const scrollTop = $(window).scrollTop();
const scrollLeft = $(window).scrollLeft();
// Position badge top-right của parent và show
$badge.css({
display: 'inline-block',
visibility: 'visible',
opacity: 1,
top: (offset.top - scrollTop) + 'px',
left: (offset.left + $parent.outerWidth() - badgeWidth - scrollLeft - 5) + 'px' // -5px padding
});
console.log('Showing badge for:', parentAddress, 'at position:', $badge.css('top'), $badge.css('left'));
$parent.addClass('highlight-border');
}
function hidePhanTichBadgeForParent($parent) {
const $badge = $parent.find('.badge-phan-tich-container').first();
if ($badge.length === 0) return;
$badge.css({display: 'none', opacity: 0});
$parent.removeClass('highlight-border');
}
// Event delegation cho hover vào parent elements (dieu, khoan,...) - attach badge nếu chưa có, rồi show
$(document).on('mouseenter', '#tab_noi_dung_vb phan, #tab_noi_dung_vb chuong, #tab_noi_dung_vb muc, #tab_noi_dung_vb tieumuc, #tab_noi_dung_vb dieu, #tab_noi_dung_vb khoan, #tab_noi_dung_vb diem', function(e) {
// Stop propagation để tránh highlight parent khi hover vào child
e.stopPropagation();
const $parent = $(this);
const address = $parent.attr('address');
// Set flag hovering
$parent.data('hovering', true);
// Cancel timeout nếu có
const timeoutId = $parent.data('hideTimeout');
if (timeoutId) {
clearTimeout(timeoutId);
}
// Ẩn highlight của tất cả parent elements khác (trừ element đang analyzing)
$('#tab_noi_dung_vb phan, #tab_noi_dung_vb chuong, #tab_noi_dung_vb muc, #tab_noi_dung_vb tieumuc, #tab_noi_dung_vb dieu, #tab_noi_dung_vb khoan, #tab_noi_dung_vb diem')
.not($parent)
.each(function() {
const $el = $(this);
// Chỉ xóa highlight-border, KHÔNG xóa highlight-border-persistent
$el.removeClass('highlight-border');
// Ẩn badge nếu KHÔNG đang analyzing
const $badge = $el.find('.badge-phan-tich-container');
if ($badge.length && !$badge.data('analyzing')) {
$badge.css({display: 'none'});
}
});
// Attach badge nếu chưa có - badge phải có data-for = address của PARENT, không phải child
if (address && $parent.find('.badge-phan-tich-container[data-for="' + address + '"]').length === 0) {
const parentType = getParentTypeName($parent.prop('tagName').toLowerCase());
// Tạo badge với data-for = address của PARENT element này
const $badge = $('Phân tích');
console.log('Creating badge for address:', address, 'parentType:', parentType);
$parent.append($badge);
$parent.addClass('has-phan-tich-badge');
}
// Show badge cho element này
if ($parent.find('.badge-phan-tich-container').length > 0) {
showPhanTichBadgeForParent($parent);
}
});
// Event delegation cho hover ra khỏi parent
$(document).on('mouseleave', '#tab_noi_dung_vb phan, #tab_noi_dung_vb chuong, #tab_noi_dung_vb muc, #tab_noi_dung_vb tieumuc, #tab_noi_dung_vb dieu, #tab_noi_dung_vb khoan, #tab_noi_dung_vb diem', function(e) {
const $parent = $(this);
const parentAddress = $parent.attr('address');
const $badge = $parent.find('.badge-phan-tich-container[data-for="' + parentAddress + '"]').first();
// Set flag parent not hovering
$parent.data('hovering', false);
// Nếu badge đang analyzing thì KHÔNG ẩn, GIỮ hiển thị
if ($badge.length > 0 && $badge.data('analyzing')) {
console.log('Badge is analyzing, keep visible');
return;
}
// Delay để có thời gian di chuột vào badge
const timeoutId = setTimeout(() => {
// Chỉ ẩn nếu cả parent và badge đều không hover và không analyzing
if ($badge.length > 0 && !$parent.data('hovering') && !$badge.data('hovering') && !$badge.data('analyzing')) {
hidePhanTichBadgeForParent($parent);
}
}, 300); // Tăng lên 300ms
$parent.data('hideTimeout', timeoutId);
});
// Hover vào badge → giữ hiển thị
$(document).on('mouseenter', '.badge-phan-tich-container', function(e) {
e.stopPropagation();
const $badge = $(this);
const $parent = $badge.parent();
$badge.data('hovering', true);
// Cancel timeout của parent
const timeoutId = $parent.data('hideTimeout');
if (timeoutId) {
clearTimeout(timeoutId);
}
});
// Hover ra khỏi badge → ẩn nếu không hover parent
$(document).on('mouseleave', '.badge-phan-tich-container', function(e) {
const $badge = $(this);
$badge.data('hovering', false);
const $parent = $badge.parent();
// Nếu badge đang analyzing thì KHÔNG ẩn, GIỮ hiển thị
if ($badge.data('analyzing') || $badge.hasClass('analyzing')) {
console.log('Badge is analyzing on mouseleave, keep visible');
return;
}
setTimeout(() => {
// Chỉ ẩn nếu cả parent và badge đều không hover và không analyzing
if (!$parent.data('hovering') && !$badge.data('hovering') && !$badge.data('analyzing') && !$badge.hasClass('analyzing')) {
hidePhanTichBadgeForParent($parent);
}
}, 300);
});
// Event delegation cho hover vào badge → hiện tooltip
$(document).on('mouseenter', '.badge-phan-tich, .badge-phan-tich-container, .badge-phan-tich-fixed', function() {
const $badge = $(this);
const parentType = $badge.attr('data-parent-type') || 'Nội dung';
if ($badge.find('.badge-tooltip').length === 0) {
const $tooltip = $('Phân tích chi tiết nội dung ' + parentType + ' này');
$badge.append($tooltip);
setTimeout(() => $tooltip.addClass('show'), 10);
}
});
// Event delegation cho hover ra khỏi badge → ẩn tooltip
$(document).on('mouseleave', '.badge-phan-tich, .badge-phan-tich-container, .badge-phan-tich-fixed', function() {
const $tooltip = $(this).find('.badge-tooltip');
if ($tooltip.length > 0) {
$tooltip.removeClass('show');
setTimeout(() => $tooltip.remove(), 300);
}
});
// Event delegation cho click badge → mở panel
$(document).on('click', '.badge-phan-tich, .badge-phan-tich-container, .badge-phan-tich-fixed', function(e) {
e.preventDefault();
e.stopPropagation();
const $badge = $(this);
console.log('Badge clicked! Element:', $badge[0]);
console.log('Badge parent:', $badge.parent().prop('tagName'), $badge.parent().attr('address'));
console.log('Badge data-for:', $badge.attr('data-for'));
console.log('Badge data-parent-type:', $badge.attr('data-parent-type'));
// Nếu badge đang analyzing thì không cho click
if ($badge.hasClass('analyzing') || $badge.data('analyzing')) {
console.log('Badge is analyzing, click ignored');
return;
}
// Lấy address từ data-for attribute
const address = $badge.attr('data-for');
console.log('Will analyze address:', address, 'vbID:', vbID);
if (address && vbID) {
openPhanTichPanel(address, vbID);
} else {
console.error('Missing address or vbID', {address, vbID});
showWarningModal('Không tìm thấy địa chỉ điều luật hoặc ID văn bản!');
}
});
// Ẩn badge khi click vào CTTD để tránh xung đột UI
$(document).on('click', 'cttd.chuthichtudong span, dctk span, dctd span', function(e) {
console.log('CTTD clicked');
// Ẩn TẤT CẢ badge KHÔNG đang analyzing (không chỉ badge của parent)
$('.badge-phan-tich-container').each(function() {
const $badge = $(this);
// Chỉ ẩn nếu KHÔNG đang analyzing
if (!$badge.data('analyzing') && !$badge.hasClass('analyzing')) {
$badge.css({display: 'none'});
console.log('Hiding badge:', $badge.attr('data-for'));
} else {
console.log('Keeping badge visible (analyzing):', $badge.attr('data-for'));
// Đảm bảo badge analyzing vẫn visible và ở đúng vị trí
const $parent = $badge.parent();
setTimeout(() => {
if ($badge.data('analyzing') || $badge.hasClass('analyzing')) {
showPhanTichBadgeForParent($parent);
console.log('Re-showing analyzing badge after CTTD click');
}
}, 100);
}
});
});
// Update badge position khi scroll hoặc resize (vì dùng position: fixed)
function updateBadgePositions() {
$('.badge-phan-tich-container:visible').each(function() {
const $badge = $(this);
const $parent = $badge.parent();
// Cập nhật position nếu parent đang hover HOẶC badge đang analyzing
if ($parent.length && ($parent.is(':hover') || $badge.data('analyzing'))) {
// Re-calculate position
const offset = $parent.offset();
const scrollTop = $(window).scrollTop();
const scrollLeft = $(window).scrollLeft();
const badgeWidth = $badge.outerWidth();
$badge.css({
top: (offset.top - scrollTop) + 'px',
left: (offset.left + $parent.outerWidth() - badgeWidth - scrollLeft - 5) + 'px'
});
}
});
}
$(window).on('scroll', updateBadgePositions);
$(window).on('resize', updateBadgePositions);
}
});