Trang chủCode functionBài viết
Code function

Hướng dẫn tạo menu chuột phải (Context Menu) cho WordPress: hỗ trợ mobile, submenu, icon

17/03/2025 388 lượt xem admin Cập nhật: 04/12/2025
Thiết kế web giá rẻ với Webdy, dịch vụ xây dựng website chuyên nghiệp ưu đãi nhất.
5/5 - (1 bình chọn)

Mở file functions.php trong child theme của bạn (nếu chưa có child theme, bạn nên tạo child theme để tránh mất thay đổi khi update theme). Thêm đoạn code sau:

Thiết kế website giá rẻ Webdy, dịch vụ thiết kế web thương hiệu và tối ưu SEO cho doanh nghiệp, giá cạnh tranh, chuyên nghiệp.

add_action('wp_footer', function () {
echo <<<'HTML'
<script>
(function(){
var CONFIG = {"title":"Webdy shortcuts","parentUrl":"https://thietkeweb.re/lien-he","background":"#ffffff","textColor":"#000000","accentColor":"#e5e7eb","mobileEnabled":true,"mobileHoldDelay":600,"submenuStyleDesktop":"flyout","submenuStyleMobile":"dropdown","items":[{"label":"Hotline","url":"tel:0902299161","icon":"https://webdy.vn/files/uploads/2024/03/call.jpg","background":"#ffe4e6","children":[]},{"label":"Zalo","url":"https://zalo.me/0902299161","icon":"https://webdy.vn/files/uploads/2024/03/i-zalo.svg","background":"#dbeafe","children":[]},{"label":"Dịch vụ","url":"https://thietkeweb.re/lien-he","icon":"https://webdy.vn/files/uploads/2024/03/menu.png","background":"#f8fafc","children":[{"label":"Thiết kế web","url":"https://thietkeweb.re/lien-he","icon":"https://webdy.vn/files/uploads/2024/03/contact.jpg","background":"#fef9c3","children":[]},{"label":"Xử lý mã độc","url":"https://thietkeweb.re/lien-he","icon":"https://webdy.vn/files/uploads/2024/03/contact.jpg","background":"#fee2e2","children":[]},{"label":"Tối ưu web","url":"https://thietkeweb.re/lien-he","icon":"https://webdy.vn/files/uploads/2024/03/contact.jpg","background":"#dcfce7","children":[]},{"label":"Tư vấn SEO","url":"https://thietkeweb.re/lien-he","icon":"https://webdy.vn/files/uploads/2024/03/contact.jpg","background":"#ede9fe","children":[]}]},{"label":"Messenger","url":"https://m.me/webdy.vn","icon":"https://webdy.vn/files/uploads/2024/03/i-messenger.svg","background":"#e0e7ff","children":[]},{"label":"Hỗ trợ website","url":"","icon":"https://webdy.vn/files/uploads/2024/03/Facebook_Logo_2019.png","background":"#f1f5f9","children":[{"label":"HỖ TRỢ WEBSITE","url":"https://zalo.me/g/noelmd215","icon":"https://webdy.vn/files/uploads/2024/03/i-zalo.svg","background":"#e0f2fe","children":[]},{"label":"Hỗ trợ thiết kế web Webdy.vn","url":"https://zalo.me/g/sbzrtr405","icon":"https://webdy.vn/files/uploads/2024/03/i-zalo.svg","background":"#dbeafe","children":[]},{"label":"Hỗ trợ thiết kế website","url":"https://www.facebook.com/groups/1746684449131527","icon":"https://webdy.vn/files/uploads/2024/03/Facebook_Logo_2019.png","background":"#c7d2fe","children":[]},{"label":"Thiết kế Website giá rẻ","url":"https://www.facebook.com/groups/1068742887589119","icon":"https://webdy.vn/files/uploads/2024/03/Facebook_Logo_2019.png","background":"#e9d5ff","children":[]}]}]};
var STYLE_ID = 'webdy-context-style';
var MENU_ID = 'webdy-context-menu';
function escapeHtml(str){ return String(str || '').replace(/[&<>\"']/g, function(ch){ return ({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;','\'':'&#39;'})[ch]; }); }
function escapeAttr(str){ return escapeHtml(str); }
function buildCss(cfg){
var bg = cfg.background || '#ffffff';
var fg = cfg.textColor || '#0f172a';
var accent = cfg.accentColor || '#e5e7eb';
return [
'.webdy-context-menu{position:fixed;z-index:2147483647;display:none;min-width:220px;background:'+bg+';color:'+fg+';border-radius:12px;padding:12px;box-shadow:0 24px 60px rgba(15,23,42,.45);font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:14px;line-height:1.5;}',
'.webdy-context-menu.is-visible{display:block;}',
'.webdy-context-menu ul{margin:0;padding:0;list-style:none;}',
'.webdy-context-menu .webdy-context-item{margin:0;padding:0;}',
'.webdy-context-menu .webdy-context-item + .webdy-context-item{margin-top:4px;}',
'.webdy-context-menu .webdy-context-link{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:10px;text-decoration:none;color:'+fg+';background:var(--item-bg,'+bg+');transition:background .2s,color .2s;}',
'.webdy-context-menu .webdy-context-link:hover{background:'+accent+';color:'+fg+';}',
'.webdy-context-menu .webdy-context-text{flex:1;min-width:0;word-break:break-word;}',
'.webdy-context-menu .webdy-context-icon{width:28px;height:28px;border-radius:9px;overflow:hidden;background:rgba(15,23,42,.08);display:flex;align-items:center;justify-content:center;flex-shrink:0;}',
'.webdy-context-menu .webdy-context-icon img{width:100%;height:100%;object-fit:cover;display:block;}',
'.webdy-context-menu .webdy-context-arrow{margin-left:12px;font-size:14px;color:'+accent+';flex-shrink:0;}',
'.webdy-context-menu .webdy-context-sub{position:absolute;min-width:210px;background:'+bg+';color:'+fg+';border-radius:12px;padding:12px;box-shadow:0 24px 60px rgba(15,23,42,.45);display:none;z-index:99;}',
'.webdy-context-menu .webdy-context-sub.is-open{display:block;}',
'.webdy-context-menu .webdy-context-sub ul{margin:0;padding:0;list-style:none;}',
'.webdy-context-menu .webdy-context-sub.align-left{left:auto;right:calc(100% + 12px);}',
'.webdy-context-menu .webdy-context-sub.align-top{top:auto;bottom:calc(100% + 8px);}',
'.webdy-context-menu.style-dropdown .webdy-context-item{position:relative;}',
'.webdy-context-menu.style-dropdown .webdy-context-item.has-children{z-index:1;}',
'.webdy-context-menu.style-dropdown .webdy-context-item.has-children.is-open{z-index:3;}',
'.webdy-context-menu.style-dropdown .webdy-context-sub{left:0;top:calc(100% + 8px);}',
'.webdy-context-menu.style-flyout .webdy-context-item{position:relative;}',
'.webdy-context-menu.style-flyout .webdy-context-sub{left:calc(100% + 12px);top:0;}'
].join('');
}
function renderItems(items, layout){
items = Array.isArray(items) ? items : [];
var currentLayout = layout === 'dropdown' ? 'dropdown' : 'flyout';
var html = ['<ul class="webdy-context-list">'];
items.forEach(function(item){
if (!item || !item.label){ return; }
var hasChildren = Array.isArray(item.children) && item.children.some(function(child){ return child && child.label; });
var label = escapeHtml(item.label);
var url = item.url ? escapeAttr(item.url) : '#';
var rowStyle = item.background ? ' style="--item-bg:'+escapeAttr(item.background)+'"' : '';
html.push('<li class="webdy-context-item'+(hasChildren ? ' has-children' : '')+'">');
html.push('<a class="webdy-context-link" href="'+url+'" target="_blank" rel="noopener"'+rowStyle+'>');
if (item.icon){ html.push('<span class="webdy-context-icon"><img src="'+escapeAttr(item.icon)+'" alt=""></span>'); }
html.push('<span class="webdy-context-text">'+label+'</span>');
if (hasChildren){ html.push('<span class="webdy-context-arrow">'+(currentLayout === 'flyout' ? '&rsaquo;' : '&dtrif;')+'</span>'); }
html.push('</a>');
if (hasChildren){ html.push('<div class="webdy-context-sub">'+renderItems(item.children, currentLayout)+'</div>'); }
html.push('</li>');
});
html.push('</ul>');
return html.join('');
}
function buildMarkup(cfg, layout){ return renderItems(cfg.items, layout); }
function ensureStyles(cfg){
var style = document.getElementById(STYLE_ID);
if (!style){ style = document.createElement('style'); style.id = STYLE_ID; document.head.appendChild(style); }
style.textContent = buildCss(cfg);
}
ensureStyles(CONFIG);
var menu = document.getElementById(MENU_ID);
if (menu){ menu.parentNode.removeChild(menu); }
menu = document.createElement('div');
menu.id = MENU_ID;
var initialLayout = CONFIG.submenuStyleDesktop === 'dropdown' ? 'dropdown' : 'flyout';
menu.className = 'webdy-context-menu ' + (initialLayout === 'flyout' ? 'style-flyout' : 'style-dropdown');
menu.innerHTML = buildMarkup(CONFIG, initialLayout);
document.body.appendChild(menu);
function setupSubmenus(){
var parents = menu.querySelectorAll('.has-children');
parents.forEach(function(parent){
var sub = parent.querySelector('.webdy-context-sub');
if (!sub){ return; }
parent.addEventListener('mouseenter', function(){
parent.classList.add('is-open');
sub.classList.add('is-open');
sub.classList.remove('align-left');
sub.classList.remove('align-top');
adjustSubmenu(sub);
});
parent.addEventListener('mouseleave', function(){
parent.classList.remove('is-open');
sub.classList.remove('is-open');
sub.classList.remove('align-left');
sub.classList.remove('align-top');
});
var link = parent.querySelector('.webdy-context-link');
if (link){
link.addEventListener('click', function(event){
if (!allowMobile){ return; }
if (!sub || sub.classList.contains('is-open')){ return; }
event.preventDefault();
menu.querySelectorAll('.webdy-context-item.is-open').forEach(function(item){
if (item === parent){ return; }
item.classList.remove('is-open');
var nested = item.querySelector('.webdy-context-sub');
if (nested){
nested.classList.remove('is-open');
nested.classList.remove('align-left');
nested.classList.remove('align-top');
}
});
parent.classList.add('is-open');
sub.classList.add('is-open');
sub.classList.remove('align-left');
sub.classList.remove('align-top');
adjustSubmenu(sub);
});
}
});
}
function adjustSubmenu(sub){
if (!sub){ return; }
var rect = sub.getBoundingClientRect();
var vw = window.innerWidth || document.documentElement.clientWidth;
var vh = window.innerHeight || document.documentElement.clientHeight;
if (rect.right > vw - 8){ sub.classList.add('align-left'); }
if (rect.bottom > vh - 8){ sub.classList.add('align-top'); }
}
function hideMenu(){
menu.classList.remove('is-visible');
menu.querySelectorAll('.webdy-context-sub').forEach(function(sub){
sub.classList.remove('is-open');
sub.classList.remove('align-left');
sub.classList.remove('align-top');
});
menu.querySelectorAll('.webdy-context-item.is-open').forEach(function(item){
item.classList.remove('is-open');
});
}
function showMenu(x, y){
menu.style.left = x + 'px';
menu.style.top = y + 'px';
menu.classList.add('is-visible');
adjustMenu();
}
function adjustMenu(){
var rect = menu.getBoundingClientRect();
var vw = window.innerWidth || document.documentElement.clientWidth;
var vh = window.innerHeight || document.documentElement.clientHeight;
var left = rect.left;
var top = rect.top;
if (rect.right > vw){ left = Math.max(8, vw - rect.width - 8); }
if (rect.bottom > vh){ top = Math.max(8, vh - rect.height - 8); }
menu.style.left = left + 'px';
menu.style.top = top + 'px';
}
function openMenuAt(x, y, mode){
var layout = mode === 'mobile' ? CONFIG.submenuStyleMobile : CONFIG.submenuStyleDesktop;
layout = layout === 'dropdown' ? 'dropdown' : 'flyout';
ensureStyles(CONFIG);
menu.className = 'webdy-context-menu ' + (layout === 'flyout' ? 'style-flyout' : 'style-dropdown');
menu.innerHTML = buildMarkup(CONFIG, layout);
setupSubmenus();
showMenu(x, y);
}
var mobileFlag = Object.prototype.hasOwnProperty.call(CONFIG, 'mobileEnabled') ? CONFIG.mobileEnabled : true;
var allowMobile = !(mobileFlag === false || mobileFlag === 0 || mobileFlag === '0' || (typeof mobileFlag === 'string' && mobileFlag.toLowerCase() === 'false'));
var holdDelay = Math.max(200, parseInt(CONFIG.mobileHoldDelay, 10) || 600);
var touchTimer = null;
var touchPoint = { x: 0, y: 0 };
var activeTouch = null;
var touchTriggered = false;
var suppressNextClick = false;
var lastTouchTime = 0;
var TOUCH_MOVE_LIMIT = 12;
function cancelTouchTimer(){
if (touchTimer){
clearTimeout(touchTimer);
touchTimer = null;
}
}
document.addEventListener('touchstart', function(){
lastTouchTime = Date.now();
}, true);
document.addEventListener('contextmenu', function(event){
if (event.defaultPrevented){ return; }
if (event.target && event.target.closest && event.target.closest('.webdy-context-ignore')){ return; }
if (event.ctrlKey || event.metaKey){ return; }
if (!allowMobile && Date.now() - lastTouchTime < 800){ return; }
event.preventDefault();
openMenuAt(event.clientX, event.clientY, 'desktop');
});
document.addEventListener('click', function(event){
if (suppressNextClick){
suppressNextClick = false;
event.preventDefault();
event.stopPropagation();
}
}, true);
if (allowMobile){
document.addEventListener('touchstart', function(event){
if (event.touches.length !== 1){
cancelTouchTimer();
return;
}
var target = event.target;
if (target && target.closest && target.closest('.webdy-context-ignore')){ return; }
var touch = event.touches[0];
touchPoint.x = touch.clientX;
touchPoint.y = touch.clientY;
activeTouch = touch.identifier;
touchTriggered = false;
cancelTouchTimer();
touchTimer = setTimeout(function(){
touchTimer = null;
touchTriggered = true;
suppressNextClick = true;
openMenuAt(touchPoint.x, touchPoint.y, 'mobile');
}, holdDelay);
});
document.addEventListener('touchmove', function(event){
if (touchTimer === null){ return; }
var touch = null;
for (var i = 0; i < event.touches.length; i++){
if (event.touches[i].identifier === activeTouch){ touch = event.touches[i]; break; }
}
if (!touch){ return; }
var dx = Math.abs(touch.clientX - touchPoint.x);
var dy = Math.abs(touch.clientY - touchPoint.y);
if (dx > TOUCH_MOVE_LIMIT || dy > TOUCH_MOVE_LIMIT){
cancelTouchTimer();
}
});
document.addEventListener('touchend', function(event){
var ended = false;
for (var i = 0; i < event.changedTouches.length; i++){
if (event.changedTouches[i].identifier === activeTouch){ ended = true; break; }
}
if (ended){
activeTouch = null;
if (!touchTriggered){
cancelTouchTimer();
} else {
touchTriggered = false;
}
}
});
document.addEventListener('touchcancel', function(){
activeTouch = null;
cancelTouchTimer();
});
document.addEventListener('touchstart', function(event){
if (!menu.contains(event.target)){
hideMenu();
}
}, true);
}
document.addEventListener('click', hideMenu);
document.addEventListener('scroll', hideMenu, true);
window.addEventListener('blur', hideMenu);
window.addEventListener('resize', hideMenu);
})();
</script>
HTML;
});

Tự custom menu và copy code tại link: https://tool.thietkeweb.re/menu-chuot-phai

Chào ! Bạn thấy nội dung này thế nào?
webdy.vn
webdy.vn

Tạo web nhanh dùng thử miễn phí.

Chia sẻ ↗

Bài liên quan

×