var naviman_version = "no-version"; /** KIỂM TRA XEM NẾU NHƯ ĐƯỜNG DẪN DẠNG * https://cdn.jsdelivr.net/gh/khoipn/naviplus-shopify@main/${version.trim()}/uigen.min.js * THÌ LẤY PHIÊN BẢN THEO CÁI NÀY **/ var scriptUrl = document.currentScript.src; var versionMatch = scriptUrl.match(/\/(\d+\.\d+\.\d+)\/uigen\.min\.js$/); if (versionMatch) { naviman_version = versionMatch[1]; } else { // console.log("No version found in the URL"); } /**********************************************************************************/ var naviman_domain = 'https://naviman.shopifas.com/'; var naviman_css = 'https://cdn.jsdelivr.net/gh/khoipn/naviplus-shopify@main/'+ naviman_version +'/uigen.min.css'; var UIGEN_ENV = "DEPLOYMENT"; /* DEPLOY DELETE.BEGIN */ var naviman_domain = 'https://coto.naviplus.io/'; var naviman_css = naviman_domain + "uigen/uigen.css.php?v=" + Math.random(); var UIGEN_ENV = "DEVELOPMENT"; /* DEPLOY DELETE.END */ var naviman_json_cdn = "https://naviplus.b-cdn.net/naviplus/data/json"; var naviman_json_files = "https://naviplus.b-cdn.net/naviplus/data/"; var naviman_cache_miniseconds = 3600000; // 10 minutes // Kiểm tra và định nghĩa namespace navihelper nếu chưa tồn tại if (typeof navihelper === 'undefined') { navihelper = {}; } // Kiểm tra và định nghĩa class WindowVar trong namespace navihelper nếu chưa tồn tại if (typeof navihelper.WindowVar === 'undefined') { navihelper.WindowVar = class { constructor() { // Khởi tạo không gian lưu trữ nếu chưa tồn tại this.naviplusVars = this.naviplusVars || {}; } static getInstance() { // Nếu instance đã tồn tại, trả về nó if (!navihelper.WindowVar.instance) { navihelper.WindowVar.instance = new navihelper.WindowVar(); } return navihelper.WindowVar.instance; } set(varName, value) { this.naviplusVars[varName] = value; } get(varName) { return this.naviplusVars[varName] !== undefined ? this.naviplusVars[varName] : null; } isExisted(varName) { return this.naviplusVars[varName] !== undefined; } delete(varName) { if (this.isExisted(varName)) { delete this.naviplusVars[varName]; return true; } return false; } } } // Kiểm tra và khởi tạo biến windowVar trong namespace navihelper nếu chưa tồn tại if (typeof navihelper.windowVar === 'undefined') { navihelper.windowVar = navihelper.WindowVar.getInstance(); } /********************************************************************************************************************** Functions. **********************************************************************************************************************/ window.navimanData = window.navimanData || []; var naviman = (function(){ var VERTICAL_CHILDREN_WIDTH = 200; var DESKTOP_MAX_WIDTH = 400; var SCROLL_TO_HIDE = 58; var SCROLL_TO_SHOW = 58; var BOX_SHADOW = 'box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.10);'; var shop = ''; var embed_id = ''; var windowWidth = window.innerWidth; var windowHeight = window.innerHeight; var cartCount = 0; var BADGE_HIDE = 0; var BADGE_DOT = 1; var BADGE_ISCART_WITHCOUNT = 2; // Gom toàn bộ những SF-1234567 data vào 1 biến để dùng /** Khởi tạo các biến dùng chung **************************/ /** uigen/init.js ****************************************/ if (typeof NAVIGLOBAL === 'undefined') { NAVIGLOBAL = []; NAVIGLOBAL['ITEM_KINDS'] = []; NAVIGLOBAL['MENU_KINDS'] = []; NAVIGLOBAL['ITEM_KINDS'] = { ICON_IMAGE_TEXT: 1, GROUP_TITLE: 2, BLANK_SPACE: 3, BIG_IMAGE_TEXT: 4, CUSTOM_HTML: 5, BUTTON: 6 }; // TODO NAVIGLOBAL['ITEM_DISPLAY_LAYOUT'] = { TOP_DOWN: 1, LEFT_RIGHT: 2, ICON_IMAGE_ONLY: 3, TEXT_ONLY: 4, EMPTY: 5, }; NAVIGLOBAL['MENU_KINDS'] = { STICKY_TABBAR: 1, STICKY_MOBILE_HEADER: 2, /* Không dùng nữa */ STICKY_FAB_SUPPORT: 11, /*******************************/ SECTION_MOBILE_HEADER: 20, SECTION_MOBILE_MEGAMENU: 31, SECTION_MOBILE_GRID: 41, SECTION_MOBILE_BANNER: 42, /*******************************/ SECTION_DESKTOP_MEGAMENU: 131, /*******************************/ CONTEXT_SLIDE: 141 } NAVIGLOBAL['MOBILE_POSITION'] = { BOTTOM: 1, TOP: 2, RIGHT_CENTER: 3, LEFT_CENTER: 4, RIGHT_BOTTOM: 5, LEFT_BOTTOM: 6 } NAVIGLOBAL['DESKTOP_POSITION'] = { BOTTOM_CENTER_FLOAT: 0, BOTTOM_CENTER: 1, BOTTOM_RIGHT: 2, BOTTOM_LEFT: 3, BOTTOM_FULL: 4, RIGHT_TOP: 5, LEFT_TOP: 6, LEFT_FULL_TOP: 7, LEFT_FULL_CENTER: 8, RIGHT_FULL_TOP: 9, RIGHT_FULL_CENTER: 10, TOP_FULL: 11 } NAVIGLOBAL['LAYOUT'] = { DEFAULT: 1, HIGHLIGHT: 2, FLOATING: 3, FAB: 4 } } const DEFAULT_ICON_IMAGE_SIZE = 22; /** uigen/init.js END ****************************************/ /** Khởi tạo các hàm dùng chung **************************/ /** uigen/libs.js ****************************************/ var openDebugMode = function() { localStorage.setItem('debugMode', 'true'); console.log('%cDebug Mode: ON', 'color: green; font-weight: bold;'); }; var closeDebugMode = function() { localStorage.removeItem('debugMode'); console.log('%cDebug Mode: OFF', 'color: red; font-weight: bold;'); }; var isDebugMode = function() { return localStorage.getItem('debugMode') === 'true'; }; var debugModeLog = function(...args) { if (isDebugMode()) { if (args.length === 1) { console.log(args[0]); // Trường hợp chỉ có message } else { console.log(args[0], args[1]); // Trường hợp có style + message } } else { //console.warn('Debug mode is OFF. Log suppressed.'); } }; var isHadValue = function(checkVar) { if (typeof (checkVar) == 'undefined') return false; if (checkVar.toString().trim() == "") return false; return true; }; var defaultValue = function( str, defaultValue ) { if (typeof str == 'undefined') return defaultValue; if( str.toString().trim() == "" ) return defaultValue; return platformValue(str); }; var isOptimizeSEO = function( naviman_shopinfo ) { /* Hàm này được sử dụng để SEO nên đối với backend mode, không cần cho SEO Chỗ này xử lý không tối ưu nhưng cũng tạm được. *******/ if( Helper.Env.isBackendMode() ) { return false; } if (typeof naviman_shopinfo != 'undefined') { if (typeof naviman_shopinfo["plan"] != "undefined") { if( naviman_shopinfo['plan'] == 'Elite' ) return true; } } return false; }; var standardizeCSS = function(rules, className){ if (rules == "") return rules; // Step 1: Clean up comments and spaces rules = rules.replace(/\/\*[\s\S]*?\*\//g, ''); rules = rules.replace(/\s{2,}/g, ' '); rules = rules.replace(/\s*({|}|,|;|:)\s*/g, '$1'); rules = rules.replace(/ /g, ' '); rules = rules.trim(); // Step 2: Check if already prefixed if (rules.length >= className.length + 1) if (rules.substring(0, className.length + 1) == '.' + className) return rules; // Step 3: Setup var classLen = className.length, char, nextChar, isAt, isIn; className = ' #' + className + ' '; // Step 4: Handle @media blocks separately var mediaRegex = /@media[^{]+{([^{}]*{[^{}]*})+\s*}/g; var matches = []; var match; while ((match = mediaRegex.exec(rules)) !== null) { matches.push({ text: match[0], index: match.index }); } var parts = []; var lastIndex = 0; matches.forEach(function(m) { if (m.index > lastIndex) { parts.push({ type: 'normal', content: rules.substring(lastIndex, m.index) }); } parts.push({ type: 'media', content: m.text }); lastIndex = m.index + m.text.length; }); if (lastIndex < rules.length) { parts.push({ type: 'normal', content: rules.substring(lastIndex) }); } // Step 5: Process each part var result = parts.map(function(part) { if (part.type === 'normal') { return processRules(part.content, className); } else if (part.type === 'media') { var innerRules = part.content.replace(/^@media[^\{]+\{/, '').replace(/\}$/, ''); var processedInner = processRules(innerRules, className); var mediaQuery = part.content.match(/^@media[^\{]+\{/)[0]; return mediaQuery + processedInner + '}\n'; } }).join('\n'); return result.trim(); }; function processRules(rules, className) { if (!rules) return ''; rules = rules.replace(/\/\*(?:(?!\*\/)[\s\S])*\*\/|[\r\n\t]+/g, ''); rules = rules.replace(/}(\s*)@/g, '}@'); rules = rules.replace(/}(\s*)}/g, '}}'); var classLen = className.length, char, nextChar, isAt, isIn; for (var i = 0; i < rules.length-2; i++) { char = rules[i]; nextChar = rules[i+1]; if (char === '@' && nextChar !== 'f') isAt = true; if (!isAt && char === '{') isIn = true; if (isIn && char === '}') isIn = false; if ( !isIn && nextChar !== '@' && nextChar !== '}' && ( char === '}' || char === ',' || ((char === '{' || char === ';') && isAt) ) ) { rules = rules.slice(0, i+1) + className + rules.slice(i+1); i += classLen; isAt = false; } } // Prefix first selector if needed if (rules.indexOf(className) !== 0 && rules.indexOf('@') !== 0) rules = ' ' + className + rules; return rules; } var isMobileMode = function () { if (window.innerWidth <= 768) return true; return false; }; var getCurrentTemplate = function () { let path = window.location.pathname.toUpperCase().trim(); if (path == '/' || path == '') return "index"; if (path.includes('PRODUCTS')) return "products"; if (path.includes('COLLECTIONS')) return "collections"; if (path.includes('PAGES')) return "pages"; if (path.includes('BLOGS')) return "blogs"; return "others"; }; var jsonp = function(uri) { return new Promise(function(resolve, reject) { var id = '_' + Math.round(10000 * Math.random()); var callbackName = 'jsonp_callback_' + id; window[callbackName] = function(data) { delete window[callbackName]; var ele = document.getElementById(id); ele.parentNode.removeChild(ele); resolve(data); } var src = uri + '&callback=' + callbackName; var script = document.createElement('script'); script.src = src; script.id = id; script.addEventListener('error', reject); (document.getElementsByTagName('head')[0] || document.body || document.documentElement).appendChild(script) }); }; var displayElement = function( el, display, displayKind = "block" ) { if( isNull(el)) return; if( isNull(el.style)) return; if( display ) el.style.display = displayKind; else el.style.display = "none"; }; var isNull = function( object ) { if ( object == null ) return true; if ( typeof object == "undefined" ) return true; return false; }; String.prototype.strReplace = function(strR, strWith) { var esc = strR.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); var reg = new RegExp(esc, 'ig'); return this.replace(reg, strWith); }; var debugConsole = function ( object ) { if( UIGEN_ENV == "DEVELOPMENT" ) console.log( object ); }; // Kiểm tra xem nếu là icon thì trả về icon, nếu có ảnh thì chỉ hiện thị ảnh thôi var itemMedia = function(icon, image, naviman_domain, style='', iconboxpadding, /*iconBoxPaddingTop = 0, */itemExtIconSize = '', itemExtAlign = '', seoUrl = '', seoName = '') { let isHadImage = true; if (typeof (image) === 'undefined') isHadImage = false; else if (image.trim() == "") isHadImage = false; var iconStyle = ""; /*if( iconBoxPaddingTop != 0 ) { iconStyle += 'margin-bottom:' + ( iconBoxPaddingTop - 2 ) + 'px; padding-top: ' + iconBoxPaddingTop + 'px;'; }*/ /* Chỗ này kiểm tra xem nếu có colorbox thì: 1. đặt span.icon là height:fitcontent và i.ri là display;inline-block, điều này làm chiều cao của span.icon bằng với chiều cao của cả cụm icon. */ if( iconboxpadding != "" && iconboxpadding != "0" ) { iconStyle += ' height: fit-content; '; } var styleImageHeight = ''; if( itemExtIconSize != '' ) styleImageHeight += ' style="height:'+ itemExtIconSize +'px '; if(parseInt(itemExtIconSize) != DEFAULT_ICON_IMAGE_SIZE ) styleImageHeight += '; width:auto; '; if( styleImageHeight != '' ) styleImageHeight += '"'; if (!isHadImage) { var output = '' + '' + ''; if( seoUrl != '' ) output = seoUrl + output + ''; return output; } else { var imageUrl = image; if( !Helper.HTML.isExternalUrl(image) ) imageUrl = naviman_json_files + image; var output = '
' + '' + seoName + '' + '
'; if (seoUrl != '') output = seoUrl + output + ''; return output; } }; var defaultMarginPadding = function( marginPadding ) { if( marginPadding == null ) marginPadding = { 'top' : 0, 'right' : 0, 'bottom' : 0, 'left' : 0 }; marginPadding['top'] = platformValue( marginPadding['top'] ); marginPadding['right'] = platformValue( marginPadding['right'] ); marginPadding['bottom'] = platformValue( marginPadding['bottom'] ); marginPadding['left'] = platformValue( marginPadding['left'] ); if(marginPadding['top'] == '') marginPadding['top'] = 0; if(marginPadding['right'] == '') marginPadding['right'] = 0; if(marginPadding['bottom'] == '') marginPadding['bottom'] = 0; if(marginPadding['left'] == '') marginPadding['left'] = 0; return marginPadding; }; function encodeBody( url ) { var output = url; const words = output.split('body='); if( words.length == 2 ) { //console.log( words ); var body = encodeURIComponent(words[1]); output = words[0] + 'body=' + body; } return output; } function isUserLoggedIn() { try { if (window.ShopifyAnalytics.meta.page.customerId == null) return false; }catch({ name, message }) { return false; } return true; } var hexToRgba = function(hex, alpha = 1) { // Remove the leading # hex = hex.replace('#', ''); // Parse the red, green, and blue values let red = parseInt(hex.substring(0, 2), 16); let green = parseInt(hex.substring(2, 4), 16); let blue = parseInt(hex.substring(4, 6), 16); // Return the rgba string return `rgba(${red}, ${green}, ${blue}, ${alpha})`; } var isSettingBeTrue = function( checkVar, defaultValue = false ) { if (isHadValue(checkVar)) if( checkVar == true || checkVar == "true" ) return true; else return false; return defaultValue; } var removeExtraSpaces = function(str) { // Sử dụng biểu thức chính quy để thay thế nhiều khoảng trắng bằng một khoảng trắng duy nhất return str.replace(/\s+/g, ' ').trim(); } var menuSlideDesktopSubDirection = function ( data, menuKind ) { var menuClass = ''; if( menuKind == NAVIGLOBAL['MENU_KINDS']['CONTEXT_SLIDE'] ) { var isOnMobile = (window.innerWidth <= 768); if( !isOnMobile ) { if (data["setting"]["hamburgerSubDirection"] == 2) { menuClass += " hamburger-desktop-sub-leftright "; }else menuClass += " hamburger-desktop-sub-topdown "; } } return menuClass; } var menuSlidePositionClass = function ( data, menuKind ) { var menuSlidePosition = ''; var hamburgerPosition = 1; if( data["setting"]["hamburgerPosition"] != null ) hamburgerPosition = parseInt(data["setting"]["hamburgerPosition"]); if( menuKind == NAVIGLOBAL['MENU_KINDS']['CONTEXT_SLIDE'] ) { var isOnMobile = (window.innerWidth <= 768); if( isOnMobile ) { if( hamburgerPosition == 1 ) menuSlidePosition += " hamburger-left-right"; else if( hamburgerPosition == 2 ) menuSlidePosition += " hamburger-right-left "; else if( hamburgerPosition == 3 ) menuSlidePosition += " hamburger-top-down "; else if( hamburgerPosition == 4 ) menuSlidePosition += " hamburger-down-top "; else if( hamburgerPosition == 5 ) menuSlidePosition += " hamburger-fullscreen "; else if( hamburgerPosition == 6 ) menuSlidePosition += " hamburger-full-popup "; }else // Desktop { if( hamburgerPosition == 2 ) menuSlidePosition += " hamburger-right-left"; else menuSlidePosition += " hamburger-left-right "; } return menuSlidePosition; } return ""; } var menuPositionClass = function ( data ) { var menuPosition = ''; switch (parseInt(data["setting"]["mobilePosition"])) { case NAVIGLOBAL['MOBILE_POSITION']['BOTTOM']: menuPosition += " mobile-" + "bottom "; break; case NAVIGLOBAL['MOBILE_POSITION']['TOP']: menuPosition += " mobile-" + "top "; break; case NAVIGLOBAL['MOBILE_POSITION']['RIGHT_CENTER']: menuPosition += " mobile-" + "right-center "; break; case NAVIGLOBAL['MOBILE_POSITION']['LEFT_CENTER']: menuPosition += " mobile-" + "left-center "; break; case NAVIGLOBAL['MOBILE_POSITION']['RIGHT_BOTTOM']: menuPosition += " mobile-" + "right-bottom "; break; case NAVIGLOBAL['MOBILE_POSITION']['LEFT_BOTTOM']: menuPosition += " mobile-" + "left-button "; break; } switch (parseInt(data["setting"]["desktopPosition"])) { case NAVIGLOBAL['DESKTOP_POSITION']['BOTTOM_CENTER_FLOAT']: menuPosition += " desktop-" + "bottom-center-float "; break; case NAVIGLOBAL['DESKTOP_POSITION']['BOTTOM_CENTER']: menuPosition += " desktop-" + "bottom-center "; break; case NAVIGLOBAL['DESKTOP_POSITION']['BOTTOM_RIGHT']: menuPosition += " desktop-" + "bottom-right "; break; case NAVIGLOBAL['DESKTOP_POSITION']['BOTTOM_RIGHT']: menuPosition += " desktop-" + "bottom-right "; break; case NAVIGLOBAL['DESKTOP_POSITION']['BOTTOM_LEFT']: menuPosition += " desktop-" + "bottom-left "; break; case NAVIGLOBAL['DESKTOP_POSITION']['BOTTOM_FULL']: menuPosition += " desktop-" + "bottom-full "; break; case NAVIGLOBAL['DESKTOP_POSITION']['RIGHT_TOP']: menuPosition += " desktop-" + "right-top "; break; case NAVIGLOBAL['DESKTOP_POSITION']['LEFT_TOP']: menuPosition += " desktop-" + "left-top "; break; case NAVIGLOBAL['DESKTOP_POSITION']['LEFT_FULL_TOP']: menuPosition += " desktop-" + "left-full-top "; break; case NAVIGLOBAL['DESKTOP_POSITION']['LEFT_FULL_CENTER']: menuPosition += " desktop-" + "left-full-center "; break; case NAVIGLOBAL['DESKTOP_POSITION']['RIGHT_FULL_TOP']: menuPosition += " desktop-" + "right-full-top "; break; case NAVIGLOBAL['DESKTOP_POSITION']['RIGHT_FULL_CENTER']: menuPosition += " desktop-" + "right-full-center "; break; case NAVIGLOBAL['DESKTOP_POSITION']['TOP_FULL']: menuPosition += " desktop-" + "top-full "; break; } return menuPosition; } var getSEOUrl = function (itemUrl) { var currentDomain = window.location.origin; itemUrl = itemUrl.trim(); if (itemUrl === "") return currentDomain; if (itemUrl === "#") return itemUrl; // Kiểm tra xem itemUrl có phải là một URL tuyệt đối (bắt đầu bằng http:// hoặc https://) không if (itemUrl.startsWith("http://") || itemUrl.startsWith("https://")) { return itemUrl; } // Loại bỏ các giá trị đặc biệt const invalidPrefixes = ["open:", "scroll:", "javascript:", "tel:", "sms:", "mailto:", "share:"]; if (invalidPrefixes.some(prefix => itemUrl.includes(prefix))) { return ""; } return currentDomain + "/" + itemUrl; }; var getMenuKind = function( naviman_shopinfo, embed_id ) { if( Helper.Env.isBackendMode() ) { if( typeof fakeMenuKind != "undefined" ) return fakeMenuKind; return "1"; } if( typeof naviman_shopinfo != "undefined" ) { if (typeof naviman_shopinfo["bottombars"] != "undefined") { if (typeof naviman_shopinfo["bottombars"][embed_id] != "undefined") { return naviman_shopinfo["bottombars"][embed_id]; } } } return -1; } var getMenuKindString = function(naviman_shopinfo, embed_id) { var menuKind = getMenuKind(naviman_shopinfo, embed_id); const menuKindMap = { [NAVIGLOBAL['MENU_KINDS']['STICKY_TABBAR']]: "STICKY_TABBAR", [NAVIGLOBAL['MENU_KINDS']['STICKY_MOBILE_HEADER']]: "STICKY_MOBILE_HEADER", [NAVIGLOBAL['MENU_KINDS']['STICKY_FAB_SUPPORT']]: "STICKY_FAB_SUPPORT", [NAVIGLOBAL['MENU_KINDS']['SECTION_MOBILE_HEADER']]: "SECTION_MOBILE_HEADER", [NAVIGLOBAL['MENU_KINDS']['SECTION_MOBILE_MEGAMENU']]: "SECTION_MOBILE_MEGAMENU", [NAVIGLOBAL['MENU_KINDS']['SECTION_MOBILE_GRID']]: "SECTION_MOBILE_GRID", [NAVIGLOBAL['MENU_KINDS']['SECTION_MOBILE_BANNER']]: "SECTION_MOBILE_BANNER", [NAVIGLOBAL['MENU_KINDS']['SECTION_DESKTOP_MEGAMENU']]: "SECTION_DESKTOP_MEGAMENU", [NAVIGLOBAL['MENU_KINDS']['CONTEXT_SLIDE']]: "CONTEXT_SLIDE" }; return menuKindMap[menuKind] || ""; }; var getMenuKindStringById = function(menuKind) { const menuKindMap = { [NAVIGLOBAL['MENU_KINDS']['STICKY_TABBAR']]: "STICKY_TABBAR", [NAVIGLOBAL['MENU_KINDS']['STICKY_MOBILE_HEADER']]: "STICKY_MOBILE_HEADER", [NAVIGLOBAL['MENU_KINDS']['STICKY_FAB_SUPPORT']]: "STICKY_FAB_SUPPORT", [NAVIGLOBAL['MENU_KINDS']['SECTION_MOBILE_HEADER']]: "SECTION_MOBILE_HEADER", [NAVIGLOBAL['MENU_KINDS']['SECTION_MOBILE_MEGAMENU']]: "SECTION_MOBILE_MEGAMENU", [NAVIGLOBAL['MENU_KINDS']['SECTION_MOBILE_GRID']]: "SECTION_MOBILE_GRID", [NAVIGLOBAL['MENU_KINDS']['SECTION_MOBILE_BANNER']]: "SECTION_MOBILE_BANNER", [NAVIGLOBAL['MENU_KINDS']['SECTION_DESKTOP_MEGAMENU']]: "SECTION_DESKTOP_MEGAMENU", [NAVIGLOBAL['MENU_KINDS']['CONTEXT_SLIDE']]: "CONTEXT_SLIDE" }; return menuKindMap[menuKind] || ""; }; function removeAllEventListeners(element) { const newElement = element.cloneNode(true); // Tạo bản sao element.parentNode.replaceChild(newElement, element); // Thay thế phần tử gốc bằng bản sao return newElement; // Trả về phần tử mới } function encodeQuery(query) { if (typeof query !== 'string') return ""; let encoded = btoa(query); // Encode to Base64 return encoded.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); } function decodeQuery(encoded) { if (typeof encoded !== 'string') return ""; encoded = encoded.replace(/-/g, '+').replace(/_/g, '/'); try { return atob(encoded); } catch { return ""; } } function parseAttributes(input) { // Split by ; and , delimiters let parts = input.split(/[,;]+/); // Filter and clean valid attributes (attr=value) let validAttributes = parts .map(part => part.trim()) // Trim spaces around .filter(part => { // Only keep parts that have an = sign and no space in the attribute name return /^[a-zA-Z0-9_-]+\s*=\s*[^\s]+/.test(part); }); return validAttributes; } function formatAttributes(attrArray) { return attrArray.map(attrPair => { let [attribute, value] = attrPair.split('='); // Replace spaces in the attribute name with hyphens attribute = attribute.trim().replace(/\s+/g, '-'); // Return the formatted string with value in double quotes return `${attribute}="${value.trim()}"`; }).join(' '); } function standardizeFunctionString(funcString) { // Regular Expression để bắt các hàm dạng 'function tenHam(...) {...}' const functionDeclarationPattern = /function\s+([a-zA-Z_$][\w$]*)\s*\(([^)]*)\)\s*\{/g; // Regular Expression để bắt các hàm dạng 'var tenHam = function(...) {...}' const functionExpressionPattern = /var\s+([a-zA-Z_$][\w$]*)\s*=\s*function\s*\(([^)]*)\)\s*\{/g; // Thay thế các hàm dạng 'function tenHam(...) {...}' thành 'Navi.tenHam = function(...) {...}' var output = funcString.replace(functionDeclarationPattern, 'Navi.$1 = function($2) {'); // Thay thế các hàm dạng 'var tenHam = function(...) {...}' thành 'Navi.tenHam = function(...) {...}' output = output.replace(functionExpressionPattern, 'Navi.$1 = function($2) {'); return output; } var platformValue = function( val ) { if( val != "" ) { if( typeof val !== 'string' ) return val; // Bước 0: Cắt bỏ ký tự '|' ở đầu và cuối nếu có if (val.startsWith('|')) val = val.slice(1); if (val.endsWith('|')) val = val.slice(0, -1); // Bước 1: Kiểm tra nếu không chứa ký tự '|', trả về chính nó if (!val.includes('|')) return val; // Bước 2: Split thành array const parts = val.split('|'); // Kiểm tra kích thước và lấy phần tử tương ứng if (window.innerWidth <= 768) { return parts[0] !== '' ? parts[0].trim() : parts[1].trim() || ''; } else { return parts[1] !== '' ? parts[1].trim() : parts[0].trim() || ''; } } return val; } function getHiddenDivSize(div) { const clone = div.cloneNode(true); // Sao chép thẻ div clone.style.visibility = 'hidden'; // Ẩn nhưng vẫn render clone.style.position = 'absolute'; // Đặt ở vị trí tạm thời clone.style.display = 'block'; // Đảm bảo nó được render document.body.appendChild(clone); // Thêm clone vào DOM const width = clone.offsetWidth; const height = clone.offsetHeight; document.body.removeChild(clone); // Xóa clone khỏi DOM return { width, height }; } function isBrowserSafari() { return /^((?!chrome|android).)*safari/i.test(navigator.userAgent) && !!window.safari; } function convertPXToNumber(value) { if (!value) return 0; // Nếu giá trị là null, undefined, "" thì trả về 0 if (typeof value === "string") { let num = parseFloat(value.replace(/[^0-9.]/g, "")); // Loại bỏ ký tự không phải số hoặc dấu chấm return isNaN(num) ? 0 : num; // Nếu không có số hợp lệ, trả về 0 } return Number(value) || 0; // Nếu không phải số hợp lệ, trả về 0 } var generateActiveItems = function() { var pathName = Helper.String.trimChar(window.location.pathname, '/'); var naviItems = document.querySelectorAll(".naviItem"); for (let navi_item = 0; navi_item < naviItems.length; navi_item++) { const listItems = naviItems[navi_item].querySelectorAll('li'); for (let i = 0; i < listItems.length; i++) { let url = listItems[i].getAttribute("linkto"); if (url) { // Kiểm tra nếu url không null url = Helper.String.trimChar(url.replace(/^.*\/\/[^\/]+/, ''), '/'); if (url !== "" && Helper.String.topContain(pathName, url)) { listItems[i].classList.add("navi-active"); let parent = listItems[i]; for (let parent_index = 0; parent_index < 10; parent_index++) { parent = parent.parentElement; if (!parent) break; // Kiểm tra nếu parent là null thì thoát vòng lặp if (parent.tagName === "LI") { parent.classList.add("navi-active"); } if (parent.classList.contains('naviItem')) { break; } } } } } } }; /** uigen/libs.js END ****************************************/ var Helper = Helper || {}; Helper.HTML = Helper.HTML || {}; Helper.String = Helper.String || {}; Helper.Debug = Helper.Debug || {}; Helper.Env = Helper.Env || {}; Helper.String.isUrlContain = function (keywordsSetting) { var url = window.location.pathname + window.location.search; //window.location.href.toLowerCase(); url = url.toLowerCase() var keywords = keywordsSetting.split(','); for (let i = 0; i < keywords.length; i++) { keywords[i] = keywords[i].trim().toLowerCase(); if( keywords[i] != '' ) { if( url.includes( keywords[i] ) ) return true; } } return false; }; Helper.String.stringToArray = function (inputString) { return inputString .split(/[,;]/) // Tách chuỗi theo dấu , hoặc ; .map(item => item.trim()) // Loại bỏ khoảng trắng thừa ở đầu và cuối mỗi item .filter(item => item !== ""); // Loại bỏ các item rỗng }; Helper.String.trimChar = function(str, ch){ var start = 0, end = str.length; while(start < end && str[start] === ch) ++start; while(end > start && str[end - 1] === ch) --end; return (start > 0 || end < str.length) ? str.substring(start, end) : str; }; Helper.String.topContain = function( str, compare ) { str = str.toLowerCase().trim(); compare = compare.toLowerCase().trim(); // console.log(str + " | " + compare); if( str.trim() == "" ) if( compare.trim() == "" ) return true; if( str.trim() != "" ) if( compare.trim() == "" ) return false; if( str.length < compare.length ) return false; if (str.substring(0, compare.length).includes(compare)) { return true; } return false; }; Helper.Debug.writeBeautifyConsoleLog = function (message, color) { debugModeLog("%c" + message, "color: " + color + "; font-size: 11px"); }; Helper.Debug.writeLineConsoleLog = function (color) { console.log("%c____________________________________", "color: " + color + "; font-size: 11px"); }; Helper.Debug.welcomeScreen = function() { if (typeof naviman === 'undefined') { if (!window.isWelcomeLogged) { console.log( "%c\uD83D\uDC96 Using Navi+ (Ver "+ naviman_version +"), a Shopify Menu Builder application to create advanced menus: Tab Bar, Mega Menu, Hamburger Menu, Grid Menu, and more... %cDetail here: https://apps.shopify.com/pronavi-navigation-design", "color: green; font-size: 12px; font-weight: bold; background:#d5ffcd; padding: 4px 12px; margin: 12px 0px 0px 0px; border-radius: 8px;", "color: green; font-size: 12px; font-weight: bold; background: #FFFACD; padding: 4px 12px; margin: 1px 0px 12px 0px; border-radius: 8px; text-decoration: none;" ); window.isWelcomeLogged = true; } } } Helper.Env.isBackendMode = function () { if (typeof DEPLOY_ENVIROIMENT != 'undefined') if (DEPLOY_ENVIROIMENT == "DESIGNING") { return true; } return false; }; Helper.Env.checkBrowserSupport = function () { // Kiểm tra nếu trạng thái đã được lưu trong window if (window._browserSupportChecked) { // console.log('Browser support has already been checked.'); return; } // Thực hiện kiểm tra const supportStatus = { cookies: navigator.cookieEnabled, localStorage: typeof localStorage !== 'undefined', sessionStorage: typeof sessionStorage !== 'undefined', serviceWorkers: 'serviceWorker' in navigator, fetchAPI: typeof fetch === 'function', webSockets: 'WebSocket' in window }; // Log trạng thái thành một dòng const statusLine = Object.entries(supportStatus) .map(([feature, isSupported]) => `${feature}: ${isSupported ? 'Supported' : 'Not Supported'}`) .join(', '); debugModeLog(statusLine); // Lưu trạng thái vào window để tránh gọi lại window._browserSupportChecked = true; }; Helper.HTML.parsePaddingMargin = function (paddingVars) { var padding = { "top": 0, "right": 0, "bottom": 0, "left": 0, }; if( paddingVars == "" ) return padding; paddingVars = String(paddingVars).strReplace("px", " ").strReplace("pt", " ").strReplace(",", " ").strReplace("|", " ").strReplace(";", " "); // Tách chuỗi padding thành mảng các giá trị var values = paddingVars.split(' ').map(Number); // Gán giá trị vào các thuộc tính của đối tượng padding switch (values.length) { case 1: padding.top = values[0]; padding.right = values[0]; padding.bottom = values[0]; padding.left = values[0]; break; case 2: padding.top = values[0]; padding.right = values[1]; padding.bottom = values[0]; padding.left = values[1]; break; case 3: padding.top = values[0]; padding.right = values[1]; padding.bottom = values[2]; padding.left = values[1]; break; case 4: padding.top = values[0]; padding.right = values[1]; padding.bottom = values[2]; padding.left = values[3]; break; } return padding; }; Helper.HTML.formatPaddingTRBL = function( padding ) { if( padding.top == 0 & padding.right == 0 & padding.bottom == 0 & padding.left == 0 ) return ""; return ' padding: '+ padding.top +'px '+ padding.right +'px '+ padding.bottom +'px '+ padding.left +'px; ' } Helper.HTML.formatMarginTRBL = function( margin ) { if( margin.top == 0 & margin.right == 0 & margin.bottom == 0 & margin.left == 0 ) return ""; return ' margin: '+ margin.top +'px '+ margin.right +'px '+ margin.bottom +'px '+ margin.left +'px; ' } Helper.HTML.addStyleToMenu = function(naviman_appItem, inputStyle) { let html = ''; naviman_appItem.insertAdjacentHTML('beforebegin', html); } Helper.HTML.addStyleToHeader = function(styles) { var css = document.createElement('style'); css.type = 'text/css'; if (css.styleSheet) css.styleSheet.cssText = styles; else css.appendChild(document.createTextNode(styles)); document.getElementsByTagName("head")[0].appendChild(css); } Helper.HTML.clearCSS_JS = function (css) { if (typeof css == 'undefined') return ""; css = css.trim(); css = css.strReplace('', ''); css = css.strReplace('', ''); return css; }; Helper.HTML.isExternalUrl = function(file_path) { if (file_path.length > 5) { // Kiểm tra độ dài tối thiểu return file_path.startsWith('http://') || file_path.startsWith('https://'); } return false; }; Helper.hideNaviOverlay = function () { if( document.getElementsByClassName("naviman_app_overlay") == null ) return; if( document.getElementsByClassName("naviman_app_overlay").length == 0 ) return; document.getElementsByClassName("naviman_app_overlay")[0].style.display = 'none'; } Helper.showNaviOverlay = function () { if( document.getElementsByClassName("naviman_app_overlay") == null ) return; if( document.getElementsByClassName("naviman_app_overlay").length == 0 ) return; document.getElementsByClassName("naviman_app_overlay")[0].style.display = 'block'; /* var body = document.getElementsByTagName('body')[0]; body.style.overflow = 'hidden'; */ } Helper.closeAllDropdowns = function () { document.querySelectorAll('.naviman_app ul.children').forEach((item) => { item.style.display = "none"; }); document.querySelectorAll('.naviman_app span.arrow').forEach((item) => { item.style.display = "none"; }); // Chỗ này không chạy gì cả, tệ quá document.querySelectorAll('.naviItem .menu-expand').forEach((item) => { // Remove menu-expand of item item.classList.remove('menu-expand'); }); document.querySelectorAll('.naviman_app ul.children').forEach((item) => { item.style.height = "initial"; }); document.querySelectorAll('.naviman_app li.overlay-container').forEach((item) => { item.remove(); }); Helper.hideNaviOverlay(); } Helper.showNaviOverlayGlobal = function () { if( document.getElementsByClassName("naviman_app_overlay_global") == null ) return; if( document.getElementsByClassName("naviman_app_overlay_global").length == 0 ) return; document.getElementsByClassName("naviman_app_overlay_global")[0].style.display = 'block'; document.body.style.overflow = "hidden"; } Helper.hideNaviOverlayGlobal = function () { if( document.getElementsByClassName("naviman_app_overlay_global") == null ) return; if( document.getElementsByClassName("naviman_app_overlay_global").length == 0 ) return; document.getElementsByClassName("naviman_app_overlay_global")[0].style.display = 'none'; document.body.style.overflow = "initial"; } Helper.waitForCssToLoad = function(callback) { const checkInterval = setInterval(() => { const isCssLoaded = getComputedStyle(document.documentElement) .getPropertyValue('--is-navi-css-loaded') .trim(); if (isCssLoaded) { clearInterval(checkInterval); // Dừng kiểm tra khi CSS đã tải callback(); // Gọi hàm khi CSS đã tải xong } }, 50); // Kiểm tra mỗi 50ms để tránh ảnh hưởng hiệu suất } // Nếu ko có domain thì sẽ thêm https:// vào đầu url Helper.standalizeUrl = function(url) { if (typeof url !== 'string') return url; // Bỏ dấu / đầu và cuối const cleanedUrl = url.replace(/^\/+|\/+$/g, ''); // Lấy phần đầu tiên (trước dấu /) const firstSegment = cleanedUrl.split('/')[0]; // Kiểm tra nếu phần đầu có dấu . và trông giống domain const isDomain = /^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(firstSegment); // Nếu là domain và chưa có http/https → thêm https:// if (isDomain && !/^https?:\/\//i.test(url)) { return 'https://' + cleanedUrl; } return url; } /********************************************************************************************************************/ var Menu = Menu || {}; Menu.Common = Menu.Common || {}; Menu.Common.Level1 = Menu.Common.Level1 || {}; Menu.Common.checkContainKeywords = function(isDisplayed, naviItem ) { if( !isDisplayed ) return false; if (isHadValue(naviItem["data"]["setting"]['publishContainKeyword'])) { isDisplayed = Helper.String.isUrlContain(naviItem["data"]["setting"]['publishContainKeyword']); if( isDisplayed == false ) debugModeLog( naviItem["embed_id"] + " is hide because DONOT contain keyword: " + naviItem["data"]["setting"]['publishContainKeyword']); } if (isHadValue(naviItem["data"]["setting"]['publishDontContainKeyword'])) { isDisplayed = !Helper.String.isUrlContain(naviItem["data"]["setting"]['publishDontContainKeyword']); if( isDisplayed == false ) debugModeLog( naviItem["embed_id"] + " is hide because contain keyword: " + naviItem["data"]["setting"]['publishDontContainKeyword']); } return isDisplayed; } Menu.Common.checkPlatformMode = function(isDisplayed, naviItem) { if( !isDisplayed ) return false; var isOnMobile = window.innerWidth <= 768; if( isOnMobile ) if( naviItem["data"]["setting"]["mobileDisplay"] == false || naviItem["data"]["setting"]["mobileDisplay"] == 'false' ) isDisplayed = false; if( !isOnMobile ) if( naviItem["data"]["setting"]["desktopDisplay"] == false || naviItem["data"]["setting"]["desktopDisplay"] == 'false' ) isDisplayed = false; if( isDisplayed == false ) debugModeLog( naviItem["embed_id"] + " is hide. The cause is did not active for this platform (mobile/desktop) " ); return isDisplayed; } Menu.Common.initHTMLAppOverlayClasses = function() { if( document.getElementsByClassName("naviman_app_overlay").length == 0 ) naviman_app.insertAdjacentHTML('afterend', ''); if( document.getElementsByClassName("naviman_app_overlay_global").length == 0 ) document.body.insertAdjacentHTML('afterend', ''); }; /*****************************************************************************************************/ Menu.Common.Level1.generateExpandArrowShow = function( setting, cssNaviPrefix, menuKind ) { var addHtml = ""; if( menuKind == NAVIGLOBAL['MENU_KINDS']['CONTEXT_SLIDE'] || menuKind == NAVIGLOBAL['MENU_KINDS']['SECTION_DESKTOP_MEGAMENU'] || menuKind == NAVIGLOBAL['MENU_KINDS']['SECTION_MOBILE_MEGAMENU'] ) { if (!isSettingBeTrue(setting['expandArrowShow'], true)) { addHtml += cssNaviPrefix + ' ul.navigation > li.is-parent-top::after { content: "" !important; } '; addHtml += cssNaviPrefix + ' ul.navigation > li.is-parent::after { content: "" !important; } '; var paddingRight = 16; if( menuKind == NAVIGLOBAL['MENU_KINDS']['SECTION_MOBILE_MEGAMENU'] ) paddingRight = 12; addHtml += cssNaviPrefix + ' ul.navigation > li.item.is-parent-top { padding-right: '+ paddingRight +'px !important; } '; } } return addHtml; }; Menu.Common.Level1.generateBackground = function(setting, cssNaviPrefix, menuKind) { var addHtml = ""; if (isSettingBeTrue(setting['level1BackgroundHide'])) { // Nếu không có nền thì bỏ nền và bỏ bóng. addHtml += cssNaviPrefix + '{ background: initial; } '; addHtml += cssNaviPrefix + '{ box-shadow: none !important; } '; }else { if (isHadValue(setting['backgroundImage'])) { if (setting['backgroundImage'].includes("?")) { // Xử lý duy nhất trường hợp có opacity cho background Image var bg = setting['backgroundImage'].split("?"); var bgImage = bg[0]; var bgOpacity = parseInt(bg[1]); if (bgOpacity != 0) { addHtml += cssNaviPrefix + '{ background-image: url("' + bgImage + '"); background-size: cover; } '; addHtml += cssNaviPrefix + '{ background-color: ' + hexToRgba(setting['backgroundColor'], 1 - (bgOpacity / 100)) + '; background-blend-mode: hue; } '; } else { addHtml += cssNaviPrefix + '{ background: ' + setting['backgroundColor'] + ' } '; addHtml += cssNaviPrefix + '{ background-image: url("' + bgImage + '"); background-size: cover; } '; } } else { addHtml += cssNaviPrefix + '{ background: ' + setting['backgroundColor'] + ' } '; } } else { // Nếu ko có background thì dùng màu bình thường. if (isHadValue(setting['backgroundColor'])) addHtml += cssNaviPrefix + '{ background: ' + setting['backgroundColor'] + ' } '; else addHtml += cssNaviPrefix + '{ background: initial; } '; } } return addHtml; }; Menu.Common.Level1.generateDropshadow = function(setting, cssNaviPrefix, menuKind) { var addHtml = ""; if (! isSettingBeTrue(setting['level1Dropshadow'], true)) { // Nếu không có nền thì bỏ nền và bỏ bóng. addHtml += cssNaviPrefix + ' { box-shadow: none !important; } '; } return addHtml; }; Menu.Common.Level1.generateHeight = function(setting, cssNaviPrefix, menuKind) { var addHtml = ""; addHtml += cssNaviPrefix + 'ul li.item { height: ' + setting['height'] + 'px } '; /* Logic là: Chỉ có các dropdown menu dạng megamenu thì mới set height, còn lại thì nó sẽ Hug theo content (và content thì set height) */ if( menuKind == NAVIGLOBAL['MENU_KINDS']['SECTION_DESKTOP_MEGAMENU'] || menuKind == NAVIGLOBAL['MENU_KINDS']['SECTION_MOBILE_HEADER'] || menuKind == NAVIGLOBAL['MENU_KINDS']['SECTION_MOBILE_MEGAMENU'] ) { addHtml += cssNaviPrefix + ' ul.navigation { min-height: ' + setting['height'] + 'px } '; } return addHtml; }; Menu.Common.Level1.generateBorderRadius = function(setting, cssNaviPrefix, menuKind) { var addHtml = ""; addHtml += cssNaviPrefix + '{ border-radius: ' + setting['borderRadius'] + 'px } '; addHtml += cssNaviPrefix + ' ul li ul.children { border-radius: ' + setting['borderRadius'] + 'px; } '; // Setup border-radius của phần từ đầu tiên và cuối cùng. addHtml += cssNaviPrefix + ' ul li.item:first-child { border-radius: ' + setting['borderRadius'] + 'px 0px 0px ' + setting['borderRadius'] + 'px; } '; addHtml += cssNaviPrefix + ' ul li.item:last-child { border-radius: 0px ' + setting['borderRadius'] + 'px ' + setting['borderRadius'] + 'px 0px; } '; /* Chỉ quan tâm đến layout với dạng sticky tabbar **************************/ if( menuKind == NAVIGLOBAL['MENU_KINDS']['STICKY_TABBAR'] ) { if (isHadValue(setting['layout'])) { if (setting['layout'] == NAVIGLOBAL['LAYOUT']['DEFAULT'] || setting['layout'] == NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) { // Nếu sát lề dưới thì chỉ bo vong lề dưới thôi. if (setting["settingMargin"]["bottom"] == 0 || setting["settingMargin"]["bottom"] == "0" || setting["settingMargin"]["bottom"] == "" ) addHtml += cssNaviPrefix + '{ border-radius: ' + setting['borderRadius'] + 'px ' + setting['borderRadius'] + 'px 0px 0px } '; } if (setting['layout'] == NAVIGLOBAL['LAYOUT']['FLOATING']) { // Do nothing } if (setting['layout'] == NAVIGLOBAL['LAYOUT']['FAB']) { // Nếu là float button thì level có border-radius: 1/2 addHtml += cssNaviPrefix + ' ul li ul.children { border-radius: ' + (setting['borderRadius'] / 2) + 'px;} '; } } } return addHtml; }; Menu.Common.Level1.generateOpacity = function(setting, cssNaviPrefix, menuKind) { var addHtml = ""; if (isHadValue(setting['opacity'])) addHtml += cssNaviPrefix + '{ opacity: ' + (setting['opacity'] / 100) + ' } '; return addHtml; }; Menu.Common.Level1.generatePaddingMargin = function( setting, cssNaviPrefix, menuKind ) { var addHtml = ""; addHtml += cssNaviPrefix + ' { margin: ' + setting['settingMargin']['top'] + 'px ' + setting['settingMargin']['right'] + 'px ' + setting['settingMargin']['bottom'] + 'px ' + setting['settingMargin']['left'] + 'px ' + ' } '; addHtml += cssNaviPrefix + ' { padding: ' + setting['settingPadding']['top'] + 'px ' + setting['settingPadding']['right'] + 'px ' + setting['settingPadding']['bottom'] + 'px ' + setting['settingPadding']['left'] + 'px ' + ' } '; return addHtml; }; /* Menu.Common.Level1.generateHeight = function(menuKind, cssNaviPrefix, setting) { var addHtml = ""; return addHtml; }; */ Menu.Common.isMenuKind = function( menuKind, kind ) { /** * Checks if the given menuKind matches the specified kind category. * * @param {string} menuKind - The menu kind to check. * @param {string} kind - The category to check against. It can be "STICKY", "SECTION", or "CONTEXT". * @returns {boolean} - Returns true if the menuKind matches the specified kind category, false otherwise. * * Example usage: * var menuKind = NAVIGLOBAL['MENU_KINDS']['STICKY_TABBAR']; * var kind = "STICKY"; * console.log(Menu.Common.isMenuKind(menuKind, kind)); // Output: true */ kind = kind.toUpperCase(); if( kind == "STICKY" ) { if( menuKind == NAVIGLOBAL['MENU_KINDS']["STICKY_TABBAR"] || menuKind == NAVIGLOBAL['MENU_KINDS']["STICKY_MOBILE_HEADER"] || menuKind == NAVIGLOBAL['MENU_KINDS']["STICKY_FAB_SUPPORT"] ) return true; else return false; } if( kind == "SECTION" ) { if( menuKind == NAVIGLOBAL['MENU_KINDS']["SECTION_MOBILE_HEADER"] || menuKind == NAVIGLOBAL['MENU_KINDS']["SECTION_MOBILE_MEGAMENU"] || menuKind == NAVIGLOBAL['MENU_KINDS']["SECTION_MOBILE_GRID"] || menuKind == NAVIGLOBAL['MENU_KINDS']["SECTION_MOBILE_BANNER"] || menuKind == NAVIGLOBAL['MENU_KINDS']["SECTION_DESKTOP_MEGAMENU"] ) return true; else return false; } if( kind == "CONTEXT" ) { if( menuKind == NAVIGLOBAL['MENU_KINDS']["CONTEXT_SLIDE"]) return true; else return false; } console.log("ERROR: isMenuKind not working ********\/\/\/"); return false; }; window.menuZIndexMapNaviSticky = window.menuZIndexMapNaviSticky || {}; window.menuZindexNaviSections = window.menuZindexNaviSections || {}; Menu.Common.setTopZindex = function (menuItem, menuKind, embed_id) { if( Menu.Common.isMenuKind(menuKind, 'CONTEXT') ) return; if( Menu.Common.isMenuKind(menuKind, 'STICKY') ) { var menu = document.getElementById(embed_id); if (menu) { // Lưu z-index hiện tại nếu chưa lưu if (!window.menuZIndexMapNaviSticky[embed_id]) { var computedZIndex = window.getComputedStyle(menu).zIndex; window.menuZIndexMapNaviSticky[embed_id] = computedZIndex !== "auto" ? computedZIndex : "2"; } // Tăng lên mức cao nhất menu.style.zIndex = "2147483647"; //.naviman_app_overlay chỉ áp dụng với ticky menu thôi, section thì ko var overlay = document.querySelector('.naviman_app_overlay'); if (overlay) { var overlayZIndex = window.getComputedStyle(overlay).zIndex; window.menuZIndexMapNaviSticky["naviman_app_overlay"] = overlayZIndex !== "auto" ? computedZIndex : "2"; overlay.style.zIndex = "2147483646"; } } } // Với section thì cách làm khác hẳn: Lấy toàn bộ các section bọc ngoài của navi Menu, setup the z-index về 0, rồi thì khôi phục lại sau if (Menu.Common.isMenuKind(menuKind, 'SECTION')) { document.querySelectorAll('section').forEach(section => { // Bỏ qua section chứa div có id = embed_id if (section.querySelector('.naviItem') && !section.querySelector(`#${embed_id}`)) { var computedPosition = window.getComputedStyle(section).position; if (computedPosition === "relative") { var computedZIndex = window.getComputedStyle(section).zIndex; window.menuZindexNaviSections[section.id] = computedZIndex !== "auto" ? computedZIndex : "0"; section.style.zIndex = "0"; } } }); } } Menu.Common.removeTopZindex = function (menuItem, menuKind, embed_id) { if( Menu.Common.isMenuKind(menuKind, 'CONTEXT') ) return; if( Menu.Common.isMenuKind(menuKind, 'STICKY') ) { var menu = document.getElementById(embed_id); if (menu && window.menuZIndexMapNaviSticky[embed_id] !== undefined) { // Khôi phục z-index ban đầu menu.style.zIndex = window.menuZIndexMapNaviSticky[embed_id]; delete window.menuZIndexMapNaviSticky[embed_id]; // Xóa khỏi bộ nhớ tạm //.naviman_app_overlay chỉ áp dụng với ticky menu thôi, section thì ko var overlay = document.querySelector('.naviman_app_overlay'); if (overlay && window.menuZIndexMapNaviSticky["naviman_app_overlay"] !== undefined) { overlay.style.zIndex = window.menuZIndexMapNaviSticky["naviman_app_overlay"]; } } } // Với section thì cách làm khác hẳn: Lấy toàn bộ các section bọc ngoài của navi Menu, setup the z-index về 0, rồi thì khôi phục lại sau if (Menu.Common.isMenuKind(menuKind, 'SECTION')) { Object.keys(window.menuZindexNaviSections).forEach(sectionId => { var section = document.getElementById(sectionId); if (section) { section.style.zIndex = window.menuZindexNaviSections[sectionId]; } }); window.menuZindexNaviSections = {}; // Xóa bộ nhớ tạm } }; var Menu = Menu || {}; Menu.Sticky = Menu.Sticky || {}; Menu.Sticky.checkStickyDisplay = function(isDisplayed, naviItem, isNaviSection ) { if( !isDisplayed ) return false; if (naviItem["data"]["setting"]["displayGlobal"] == null || naviItem["data"]["setting"]["displayGlobal"] == "0") { // Logic: Nếu nhưng ko bật nhưng là block thì vẫn hiển thị bình thường. isDisplayed = false; if( isNaviSection ) isDisplayed = true; }else { let displayGlobalPages = naviItem["data"]["setting"]["displayGlobalPages"]; let currentTemplate = getCurrentTemplate(); if (!displayGlobalPages.includes(currentTemplate)) isDisplayed = false; } if( isDisplayed == false ) { console.log( naviItem["embed_id"] + " is hide. The cause is the displayGlobal: off" ); return; } return isDisplayed; }; Menu.Sticky.fixCSS_showLevel3Items_Desktop = function(menuItem, isNaviSection, menuKind, embed_id) { if (window.innerWidth < 769) return; let ulChildrent = menuItem.querySelector('ul.children'); if(menuKind == NAVIGLOBAL['MENU_KINDS']['STICKY_TABBAR'] ) { // Trên tất cả các trình duyệt thì menu sẽ không bị tràn và có thể scroll cả trong bố và con, cách lề dưới 100px (tạm thời) ulChildrent.parentElement.parentElement.style.overflow = "auto"; // Trên Safari thì chấp nhận menu sẽ bị tràn và xấu nhưng tạm ổn để nghĩ tiết // TODO: Cần phải tìm cách fix cho Safari vấn đề menu trên level 3 bị tràn trên desktop if(isBrowserSafari()) ulChildrent.parentElement.parentElement.style.overflow = "visible"; // Tại sao lại là 100px thì chả có logic gì, tạm thế để xem sao // TODO: Cần phải tìm một logic tốt hơn là menu level 3 luôn cách lề dưới 100px ulChildrent.style.bottom = "100px"; // Thuật toán: Đổi level 3 ở dạng fixed (và sẽ ăn theo level 1), do đó ta sẽ lấy mép level2 - level 1 để tính left của level 3 var rightEdgeOfLevel2 = ulChildrent.parentElement.parentElement.getBoundingClientRect().left + ulChildrent.parentElement.parentElement.offsetWidth; var leftEdgeOfLevel1 = document.getElementById(embed_id).getBoundingClientRect().left; // Thuật toán: Nếu như có setup paddingLeft của bottomBar thì trừ nốt đi const navimenuStyle = window.getComputedStyle(document.getElementById( embed_id )); ulChildrent.style.left = (rightEdgeOfLevel2 - leftEdgeOfLevel1 + convertPXToNumber(navimenuStyle.paddingLeft) ) + "px"; // Cho phép scroll bên trong của level 3 ulChildrent.style.overflow = "auto"; } }; Menu.Sticky.lockPageScrollingTabBar = function (menuKind, isLock) { if (menuKind !== NAVIGLOBAL['MENU_KINDS']['STICKY_TABBAR']) return; // console.log("lockPageScrollingTabBar", menuKind, isLock); const html = document.documentElement; const body = document.body; if (isLock) { const scrollY = window.scrollY || window.pageYOffset; // console.log("---[Show dropdown menu]---"); // Lưu trạng thái hiện tại nếu chưa có if (!body.dataset._lockScrollSaved) { body.dataset._lockScrollSaved = "true"; body._originalStyle = { htmlOverflow: html.style.overflow, bodyOverflow: body.style.overflow, bodyPosition: body.style.position, bodyTop: body.style.top, bodyLeft: body.style.left, bodyRight: body.style.right, bodyWidth: body.style.width, }; } html.style.overflow = 'hidden'; body.style.overflow = 'hidden'; body.style.position = 'fixed'; body.style.top = `-${scrollY}px`; body.style.left = '0'; body.style.right = '0'; body.style.width = '100%'; body.dataset.scrollY = scrollY; } else { // console.log("---[Hide dropdown menu]---"); const scrollY = body.dataset.scrollY ? parseInt(body.dataset.scrollY) : 0; // Phục hồi style nếu có bản sao lưu if (body._originalStyle) { html.style.overflow = body._originalStyle.htmlOverflow; body.style.overflow = body._originalStyle.bodyOverflow; body.style.position = body._originalStyle.bodyPosition; body.style.top = body._originalStyle.bodyTop; body.style.left = body._originalStyle.bodyLeft; body.style.right = body._originalStyle.bodyRight; body.style.width = body._originalStyle.bodyWidth; // Xóa bản sao lưu delete body._originalStyle; delete body.dataset._lockScrollSaved; } delete body.dataset.scrollY; window.scrollTo(0, scrollY); } }; Menu.Sticky.fixCSS_ForDesktop = function (cssNaviPrefix, setting, dragdrop, isNaviSection, section_setting) { var isOnMobile = window.innerWidth <= 768; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['FAB']) return ""; if (isOnMobile) return ""; var fixPositionBottomCenterFloat = function (setting, cssNaviPrefix, dragdrop) { var addHtml = ""; if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['BOTTOM_CENTER_FLOAT']) { addHtml += cssNaviPrefix + ' { width: ' + (DESKTOP_MAX_WIDTH * 1.3) + 'px; } '; addHtml += cssNaviPrefix + ' { left: 50%; transform: translate(-50%, 0); } '; addHtml += cssNaviPrefix + ' ul li.item{ position: relative; } '; addHtml += cssNaviPrefix + ' ul li ul.children{ left: initial; right: 0px; bottom: ' + (parseInt(setting['height']) + 1) + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; } '; addHtml += cssNaviPrefix + ' { border-radius: ' + setting['borderRadius'] + 'px } '; } return addHtml; }; var fixPositionBottomCenter = function (setting, cssNaviPrefix, dragdrop) { var addHtml = ""; if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['BOTTOM_CENTER']) { addHtml += cssNaviPrefix + ' { width: ' + (DESKTOP_MAX_WIDTH * 1.3) + 'px; } '; addHtml += cssNaviPrefix + ' { left: 50%; transform: translate(-50%, 0); } '; addHtml += cssNaviPrefix + ' ul li.item{ position: relative; } '; addHtml += cssNaviPrefix + ' ul li ul.children{ left: initial; right: 0px; bottom: ' + (parseInt(setting['height']) + 1) + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; } '; } return addHtml; }; var fixPositionBottomRight = function (setting, cssNaviPrefix, dragdrop) { var addHtml = ""; if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['BOTTOM_RIGHT']) { addHtml += cssNaviPrefix + ' { width: ' + DESKTOP_MAX_WIDTH + 'px; left: initial; right: 16px; } '; addHtml += cssNaviPrefix + ' ul li.item{ position: relative; } '; addHtml += cssNaviPrefix + ' ul li ul.children{ left: initial; right: 0px; bottom: ' + (parseInt(setting['height']) + 1) + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; } '; } return addHtml; }; var fixPositionBottomLeft = function (setting, cssNaviPrefix, dragdrop) { var addHtml = ""; if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['BOTTOM_LEFT']) { addHtml += cssNaviPrefix + ' { width: ' + DESKTOP_MAX_WIDTH + 'px; left: 16px; } '; addHtml += cssNaviPrefix + ' ul li.item{ position: relative; } '; addHtml += cssNaviPrefix + ' ul li ul.children{ left: initial; right: 0px; bottom: ' + (parseInt(setting['height']) + 1) + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; } '; } return addHtml; }; var fixPositionTopFull = function (setting, cssNaviPrefix, dragdrop) { var addHtml = ""; if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['TOP_FULL']) { addHtml += cssNaviPrefix + ' .navigation { width: ' + (DESKTOP_MAX_WIDTH * 2) + 'px; } '; addHtml += cssNaviPrefix + ' .navigation { left: initial; } '; addHtml += cssNaviPrefix + ' ul li.item{ position: relative; } '; addHtml += cssNaviPrefix + ' ul li ul.children{ left: initial; right: 0px; top: ' + (parseInt(setting['height']) + 1) + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; } '; addHtml += ' body { padding-top: ' + (parseInt(setting['height']) + 0) + 'px; }'; } return addHtml; }; var fixPositionBottomFull = function (setting, cssNaviPrefix, dragdrop) { var addHtml = ""; if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['BOTTOM_FULL']) { addHtml += cssNaviPrefix + ' .navigation { width: ' + (DESKTOP_MAX_WIDTH * 2) + 'px; } '; addHtml += cssNaviPrefix + ' .navigation { left: initial; } '; addHtml += cssNaviPrefix + ' ul li.item{ position: relative; } '; addHtml += cssNaviPrefix + ' ul li ul.children{ left: initial; right: 0px; bottom: ' + (parseInt(setting['height']) + 1) + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; } '; } return addHtml; }; var fixWindowResize = function (setting, cssNaviPrefix, dragdrop, isNaviSection) { if (!isNaviSection) { window.addEventListener('resize', function (event) { }); } } var fixPositionRightTop = function (setting, cssNaviPrefix, dragdrop) { var addHtml = ""; if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['RIGHT_TOP']) { addHtml += cssNaviPrefix + ' { width: ' + setting['height'] + 'px; left: initial; right: 0px; height: ' + ((parseInt(setting['height']) + 8) * dragdrop.length) + 'px } '; addHtml += cssNaviPrefix + ' ul li.item { width: ' + setting['height'] + 'px; height: ' + (parseInt(setting['height']) + 8) + 'px; } '; addHtml += cssNaviPrefix + ' { top: ' + ((windowHeight - ((parseInt(setting['height']) + 8) * dragdrop.length)) / 2) + 'px; }'; addHtml += cssNaviPrefix + ' { border-radius: ' + setting['borderRadius'] + 'px 0px 0px ' + setting['borderRadius'] + 'px } '; addHtml += cssNaviPrefix + ' ul li ul.children { left: -201px; bottom: initial; margin-top: -' + (parseInt(setting['height']) + 8) + 'px; width: ' + VERTICAL_CHILDREN_WIDTH + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { ' + BOX_SHADOW + ' } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) addHtml += cssNaviPrefix + ' ul li.item_primary > .inner { margin-top: 0px; margin-left: -8px } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['FLOATING']) { if (setting['bottomMargin'] != "") { addHtml += cssNaviPrefix + ' { right: ' + (parseInt(setting['bottomMargin'])) + 'px; } '; addHtml += cssNaviPrefix + ' { border-radius: ' + setting['borderRadius'] + 'px } '; } } if (isHadValue(setting['dividerColor'])) addHtml += cssNaviPrefix + ' ul li.item_divider { border-right: 0px; margin-right: 0px; border-bottom: solid 1px ' + setting['dividerColor'] + '; margin-bottom: -1px; } '; if (setting['layout'] != NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) // Nếu là layout 2 thì ko làm việc này. addHtml += cssNaviPrefix + ' ul li.item .inner {width: initial; } '; let submenuWidth = (-setting['submenuWidth'] - 1); addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; left: ' + submenuWidth + 'px; } '; addHtml += cssNaviPrefix + ' ul li.item { width: 100%; } '; } return addHtml; }; var fixPositionLeftTop = function (setting, cssNaviPrefix, dragdrop) { var addHtml = ""; if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['LEFT_TOP']) { addHtml += cssNaviPrefix + ' { width: ' + setting['height'] + 'px; right: initial; left: 0px; height: ' + ((parseInt(setting['height']) + 8) * dragdrop.length) + 'px } '; addHtml += cssNaviPrefix + ' ul li.item { width: ' + setting['height'] + 'px; height: ' + (parseInt(setting['height']) + 8) + 'px; } '; addHtml += cssNaviPrefix + ' { top: ' + ((windowHeight - ((parseInt(setting['height']) + 8) * dragdrop.length)) / 2) + 'px; }'; addHtml += cssNaviPrefix + ' { border-radius: 0px ' + setting['borderRadius'] + 'px ' + setting['borderRadius'] + 'px 0px } '; addHtml += cssNaviPrefix + ' ul li ul.children { left: ' + (parseInt(setting['height']) + 1) + 'px; bottom: initial; margin-top: -' + (parseInt(setting['height']) + 8) + 'px; width: ' + VERTICAL_CHILDREN_WIDTH + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { ' + BOX_SHADOW + ' } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) addHtml += cssNaviPrefix + ' ul li.item_primary > .inner { margin-top: 0px; margin-left: 1px } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['FLOATING']) { if (setting['bottomMargin'] != "") { addHtml += cssNaviPrefix + ' { left: ' + (parseInt(setting['bottomMargin'])) + 'px; } '; addHtml += cssNaviPrefix + ' { border-radius: ' + setting['borderRadius'] + 'px } '; } } if (isHadValue(setting['dividerColor'])) addHtml += cssNaviPrefix + ' ul li.item_divider { border-right: 0px; margin-right: 0px; border-bottom: solid 1px ' + setting['dividerColor'] + '; margin-bottom: -1px; } '; if (setting['layout'] != NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) // Nếu là layout 2 thì ko làm việc này. addHtml += cssNaviPrefix + ' ul li.item .inner {width: initial; } '; let submenuWidth = (-setting['submenuWidth'] - 1); submenuWidth = (parseInt(setting['height']) + 1); addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; left: ' + submenuWidth + 'px; } '; addHtml += cssNaviPrefix + ' ul li.item { width: 100%; } '; } return addHtml; }; var fixPositionLeftFullTop = function (setting, cssNaviPrefix, dragdrop) { var addHtml = ""; if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['LEFT_FULL_TOP']) { if (isHadValue(setting['dividerColor'])) addHtml += cssNaviPrefix + ' ul li.item_divider { border-right: 0px; margin-right: 0px; border-bottom: solid 1px ' + setting['dividerColor'] + '; margin-bottom: -1px; } '; if (setting['layout'] != NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) // Nếu là layout 2 thì ko làm việc này. addHtml += cssNaviPrefix + ' ul li.item .inner {width: initial; } '; let submenuWidth = (-setting['submenuWidth'] - 1); //if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['LEFT_TOP']) submenuWidth = (parseInt(setting['height']) + 1); addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; left: ' + submenuWidth + 'px; } '; addHtml += cssNaviPrefix + ' ul li.item { width: 100%; } '; addHtml += ' body {width: calc(100% - ' + setting['height'] + 'px); margin-left: ' + setting['height'] + 'px; } '; addHtml += cssNaviPrefix + ' { width: ' + setting['height'] + 'px; right: initial; left: 0px; top: 0px; height: 100vh; padding-top: 16px; } '; addHtml += cssNaviPrefix + ' ul li.item { width: ' + setting['height'] + 'px; height: ' + (parseInt(setting['height']) + 8) + 'px; } '; addHtml += cssNaviPrefix + ' { border-radius: 0px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { left: ' + (parseInt(setting['height']) + 1) + 'px; bottom: initial; margin-top: -' + (parseInt(setting['height']) + 8) + 'px; width: ' + VERTICAL_CHILDREN_WIDTH + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { ' + BOX_SHADOW + ' } '; addHtml += cssNaviPrefix + ' { padding-top: 16px; } '; addHtml += cssNaviPrefix + ' ul li.item { width: 100%; min-width: 24px; } '; // Fix lỗi nếu padding quá lớn thì bị dồn cục } return addHtml; }; var fixPositionLeftFullCenter = function (setting, cssNaviPrefix, dragdrop) { var addHtml = ""; if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['LEFT_FULL_CENTER']) { if (isHadValue(setting['dividerColor'])) addHtml += cssNaviPrefix + ' ul li.item_divider { border-right: 0px; margin-right: 0px; border-bottom: solid 1px ' + setting['dividerColor'] + '; margin-bottom: -1px; } '; if (setting['layout'] != NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) // Nếu là layout 2 thì ko làm việc này. addHtml += cssNaviPrefix + ' ul li.item .inner {width: initial; } '; let submenuWidth = (-setting['submenuWidth'] - 1); addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; left: ' + submenuWidth + 'px; } '; addHtml += cssNaviPrefix + ' ul li.item { width: 100%; } '; addHtml += ' body {width: calc(100% - ' + setting['height'] + 'px); margin-left: ' + setting['height'] + 'px; } '; addHtml += cssNaviPrefix + ' { width: ' + setting['height'] + 'px; right: initial; left: 0px; top: 0px; height: 100vh; padding-top: 16px; } '; addHtml += cssNaviPrefix + ' ul li.item { width: ' + setting['height'] + 'px; height: ' + (parseInt(setting['height']) + 8) + 'px; } '; addHtml += cssNaviPrefix + ' { border-radius: 0px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { left: ' + (parseInt(setting['height']) + 1) + 'px; bottom: initial; margin-top: -' + (parseInt(setting['height']) + 8) + 'px; width: ' + VERTICAL_CHILDREN_WIDTH + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { ' + BOX_SHADOW + ' } '; let bodyPaddingTop = (window.innerHeight - (parseInt(setting['height']) + 8) * dragdrop.length) / 2; addHtml += cssNaviPrefix + ' { padding-top: ' + bodyPaddingTop + 'px; } '; addHtml += cssNaviPrefix + ' ul li.item { width: 100%; min-width: 24px; } '; // Fix lỗi nếu padding quá lớn thì bị dồn cục } return addHtml; }; var fixPositionRightFullTop = function (setting, cssNaviPrefix, dragdrop) { var addHtml = ""; if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['RIGHT_FULL_TOP']) { if (isHadValue(setting['dividerColor'])) addHtml += cssNaviPrefix + ' ul li.item_divider { border-right: 0px; margin-right: 0px; border-bottom: solid 1px ' + setting['dividerColor'] + '; margin-bottom: -1px; } '; if (setting['layout'] != NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) // Nếu là layout 2 thì ko làm việc này. addHtml += cssNaviPrefix + ' ul li.item .inner {width: initial; } '; let submenuWidth = (-setting['submenuWidth'] - 1); addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; left: ' + submenuWidth + 'px; } '; addHtml += cssNaviPrefix + ' ul li.item { width: 100%; } '; addHtml += ' body {width: calc(100% - ' + setting['height'] + 'px); margin-right: ' + setting['height'] + 'px; } '; addHtml += cssNaviPrefix + ' { width: ' + setting['height'] + 'px; right: 0; left: initial; top: 0px; height: 100vh; padding-top: 16px; } '; addHtml += cssNaviPrefix + ' ul li.item { width: ' + setting['height'] + 'px; height: ' + (parseInt(setting['height']) + 8) + 'px; } '; addHtml += cssNaviPrefix + ' { border-radius: 0px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { right: ' + (parseInt(setting['height']) + 1) + 'px; bottom: initial; margin-top: -' + (parseInt(setting['height']) + 8) + 'px; width: ' + VERTICAL_CHILDREN_WIDTH + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { ' + BOX_SHADOW + ' } '; addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; left: ' + submenuWidth + 'px; } '; addHtml += cssNaviPrefix + ' { padding-top: 16px; } '; addHtml += cssNaviPrefix + ' ul li.item { width: 100%; min-width: 24px; } '; // Fix lỗi nếu padding quá lớn thì bị dồn cục } return addHtml; }; var fixPositionRightFullCenter = function (setting, cssNaviPrefix, dragdrop) { var addHtml = ""; if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['RIGHT_FULL_CENTER']) { if (isHadValue(setting['dividerColor'])) addHtml += cssNaviPrefix + ' ul li.item_divider { border-right: 0px; margin-right: 0px; border-bottom: solid 1px ' + setting['dividerColor'] + '; margin-bottom: -1px; } '; if (setting['layout'] != NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) // Nếu là layout 2 thì ko làm việc này. addHtml += cssNaviPrefix + ' ul li.item .inner {width: initial; } '; let submenuWidth = (-setting['submenuWidth'] - 1); addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; left: ' + submenuWidth + 'px; } '; addHtml += cssNaviPrefix + ' ul li.item { width: 100%; } '; addHtml += ' body {width: calc(100% - ' + setting['height'] + 'px); margin-right: ' + setting['height'] + 'px; } '; addHtml += cssNaviPrefix + ' { width: ' + setting['height'] + 'px; right: 0; left: initial; top: 0px; height: 100vh; padding-top: 16px; } '; addHtml += cssNaviPrefix + ' ul li.item { width: ' + setting['height'] + 'px; height: ' + (parseInt(setting['height']) + 8) + 'px; } '; addHtml += cssNaviPrefix + ' { border-radius: 0px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { right: ' + (parseInt(setting['height']) + 1) + 'px; bottom: initial; margin-top: -' + (parseInt(setting['height']) + 8) + 'px; width: ' + VERTICAL_CHILDREN_WIDTH + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { ' + BOX_SHADOW + ' } '; addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; left: ' + submenuWidth + 'px; } '; if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['RIGHT_FULL_TOP']) addHtml += cssNaviPrefix + ' { padding-top: 16px; } '; else if (setting['desktopPosition'] == 10) { let bodyPaddingTop = (window.innerHeight - (parseInt(setting['height']) + 8) * dragdrop.length) / 2; addHtml += cssNaviPrefix + ' { padding-top: ' + bodyPaddingTop + 'px; } '; } addHtml += cssNaviPrefix + ' ul li.item { width: 100%; min-width: 24px; } '; // Fix lỗi nếu padding quá lớn thì bị dồn cục } return addHtml; }; var fixPositionNaviSection = function (setting, cssNaviPrefix, dragdrop) { var addHtml = ""; if (true) { addHtml += cssNaviPrefix + ' { bottom: initial; top:0px; } '; //if(section_setting['not_sticky'] == false || section_setting['not_sticky'] == "false" ) // Nếu là loại sticky thì mới + thêm padding-top cho boddy // addHtml += ' body {padding-top: ' + setting['height'] + 'px;} '; addHtml += cssNaviPrefix + ' ul li ul.children { bottom: initial; top: ' + (parseInt(setting['height']) + 0) + 'px; ' + BOX_SHADOW + ' } '; //addHtml += cssNaviPrefix + ' { border-radius: 0px 0px ' + setting['borderRadius'] + 'px ' + setting['borderRadius'] + 'px } '; // Thêm cái line ở giữa level 1 và 2 addHtml += cssNaviPrefix + ' ul li ul.children { border-top: solid 1px rgba(0,0,0,0.05); border-bottom:0px; } '; addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; } '; } return addHtml; }; let html = ' @media only screen and (min-width: 769px) {'; //-------------------------------------------------------- if (!isNaviSection) { html += fixPositionBottomCenterFloat(setting, cssNaviPrefix, dragdrop); html += fixPositionBottomCenter(setting, cssNaviPrefix, dragdrop); html += fixPositionBottomRight(setting, cssNaviPrefix, dragdrop); html += fixPositionBottomLeft(setting, cssNaviPrefix, dragdrop); html += fixPositionBottomFull(setting, cssNaviPrefix, dragdrop); html += fixPositionRightTop(setting, cssNaviPrefix, dragdrop); html += fixPositionLeftTop(setting, cssNaviPrefix, dragdrop); html += fixPositionLeftFullTop(setting, cssNaviPrefix, dragdrop); html += fixPositionLeftFullCenter(setting, cssNaviPrefix, dragdrop); html += fixPositionRightFullTop(setting, cssNaviPrefix, dragdrop); html += fixPositionRightFullCenter(setting, cssNaviPrefix, dragdrop); html += fixPositionTopFull(setting, cssNaviPrefix, dragdrop); } else { html += fixPositionNaviSection(setting, cssNaviPrefix, dragdrop); } html += fixWindowResize(setting, cssNaviPrefix, dragdrop, isNaviSection); //-------------------------------------------------------- html += '}'; return html; }; Menu.Sticky.fixCSS_ForMobile = function(cssNaviPrefix, setting, dragdrop, section_setting) { var isOnMobile = window.innerWidth <= 768; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['FAB']) return ""; if (!isOnMobile) return ""; var fixPositionBottom = function (setting, cssNaviPrefix, dragdrop, section_setting) { var addHtml = ""; if (setting['mobilePosition'] == NAVIGLOBAL['MOBILE_POSITION']['BOTTOM']) { // Thêm footer padding-bottom // Fix: Thêm một khoảng trống ở dưới body, (nhưng nếu auto hide thì bỏ qua) if (setting['mobileAutoHide'] != "true" && setting['mobileAutoHide'] != true) { addHtml += ' body { padding-bottom: ' + (parseInt(setting['height']) + 0) + 'px; }'; } // Fix: Hất bóng shadow lên. addHtml += cssNaviPrefix + ' { box-shadow: 0px -4px 8px 0px rgba(0, 0, 0, 0.05); } '; // Fix: Nếu padding-left, right được set, thì sub menu (level 2) vẫn phải full screen if( parseInt(setting['settingPadding']['left']) + parseInt(setting['settingPadding']['right']) > 0 ) { addHtml += cssNaviPrefix + 'ul li ul.children { width: calc( 100% + ' + (parseInt(setting['settingPadding']['left']) + parseInt(setting['settingPadding']['right'])) + 'px ); } '; if (parseInt(setting['settingPadding']['left']) > 0) addHtml += cssNaviPrefix + 'ul li ul.children { left: -' + parseInt(setting['settingPadding']['left']) + 'px; } '; } // Fix: Nếu margin-left, right được set, set width của menu để không bị tràn if (setting['settingMargin']['left'] != 0 || setting['settingMargin']['right'] != 0) { addHtml += cssNaviPrefix + ' { width: calc( 100% - ' + (parseInt(setting['settingMargin']['left']) + parseInt(setting['settingMargin']['right'])) + 'px) }; '; } } return addHtml; }; var fixPositionTop = function (setting, cssNaviPrefix, dragdrop, section_setting) { var addHtml = ""; if (setting['mobilePosition'] == NAVIGLOBAL['MOBILE_POSITION']['TOP']) { addHtml += cssNaviPrefix + ' { bottom: initial; top:0px; } '; if(section_setting['not_sticky'] == false || section_setting['not_sticky'] == "false" ) // Nếu là loại sticky thì mới + thêm padding-top cho boddy addHtml += ' body {padding-top: ' + setting['height'] + 'px;} '; addHtml += cssNaviPrefix + ' ul li ul.children { bottom: initial; top: ' + (parseInt(setting['height']) + 0) + 'px; ' + BOX_SHADOW + ' } '; addHtml += cssNaviPrefix + ' { border-radius: 0px 0px ' + setting['borderRadius'] + 'px ' + setting['borderRadius'] + 'px } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) addHtml += cssNaviPrefix + ' ul li.item_primary > .inner { margin-top: 0px } '; // Fix: Float là loại thứ 3, ko phải FAB if (setting['layout'] == NAVIGLOBAL['LAYOUT']['FLOATING']) { if (setting['bottomMargin'] != 0) { addHtml += cssNaviPrefix + ' { bottom: initial; top: ' + (parseInt(setting['bottomMargin'])) + 'px; } '; addHtml += cssNaviPrefix + ' { border-radius: ' + setting['borderRadius'] + 'px } '; addHtml += ' body {padding-top: ' + (parseInt(setting['height']) + parseInt(setting['bottomMargin']) + 8) + 'px} '; } } // Thêm cái line ở giữa level 1 và 2 addHtml += cssNaviPrefix + ' ul li ul.children { border-top: solid 1px rgba(0,0,0,0.05); border-bottom:0px; } '; // Fix: Nếu padding-left, right được set, thì sub menu (level 2) vẫn phải full screen if( parseInt(setting['settingPadding']['left']) + parseInt(setting['settingPadding']['right']) > 0 ) { addHtml += cssNaviPrefix + 'ul li ul.children { width: calc( 100% + ' + (parseInt(setting['settingPadding']['left']) + parseInt(setting['settingPadding']['right'])) + 'px ); } '; if (parseInt(setting['settingPadding']['left']) > 0) addHtml += cssNaviPrefix + 'ul li ul.children { left: -' + parseInt(setting['settingPadding']['left']) + 'px; } '; } // Fix: Nếu margin-left, right được set, set width của menu để không bị tràn if (setting['settingMargin']['left'] != 0 || setting['settingMargin']['right'] != 0) { addHtml += cssNaviPrefix + ' { width: calc( 100% - ' + (parseInt(setting['settingMargin']['left']) + parseInt(setting['settingMargin']['right'])) + 'px) }; '; } } return addHtml; }; var fixPositionRightCenter = function (setting, cssNaviPrefix, dragdrop, section_setting) { var addHtml = ""; if (setting['mobilePosition'] == NAVIGLOBAL['MOBILE_POSITION']['RIGHT_CENTER']) { addHtml += cssNaviPrefix + ' { width: ' + setting['height'] + 'px; left: initial; right: 0px; height: ' + ((parseInt(setting['height']) + 8) * dragdrop.length) + 'px } '; addHtml += cssNaviPrefix + ' ul li.item { width: ' + setting['height'] + 'px; height: ' + (parseInt(setting['height']) + 8) + 'px; } '; addHtml += cssNaviPrefix + ' { top: ' + ((windowHeight - ((parseInt(setting['height']) + 8) * dragdrop.length)) / 2) + 'px; }'; addHtml += cssNaviPrefix + ' { border-radius: ' + setting['borderRadius'] + 'px 0px 0px ' + setting['borderRadius'] + 'px } '; addHtml += cssNaviPrefix + ' ul li ul.children { left: -201px; bottom: initial; margin-top: -' + (parseInt(setting['height']) + 8) + 'px; width: ' + VERTICAL_CHILDREN_WIDTH + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.10); } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) addHtml += cssNaviPrefix + ' ul li.item_primary > .inner { margin-top: 0px; margin-left: -8px } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['FLOATING']) { if (setting['bottomMargin'] != "") { addHtml += cssNaviPrefix + ' { right: ' + (parseInt(setting['bottomMargin'])) + 'px; } '; addHtml += cssNaviPrefix + ' { border-radius: ' + setting['borderRadius'] + 'px } '; } } if (isHadValue(setting['dividerColor'])) addHtml += cssNaviPrefix + ' ul li.item_divider { border-right: 0px; margin-right: 0px; border-bottom: solid 1px ' + setting['dividerColor'] + '; margin-bottom: -1px; } '; addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children {left: ' + (-(setting['submenuWidth']) - 1) + 'px; } '; /*if (setting['layout'] != NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) addHtml += cssNaviPrefix + ' ul li.item .inner { padding: 8px 0px 0px 0px; } ';*/ } return addHtml; }; var fixPositionRightBottom = function (setting, cssNaviPrefix, dragdrop, section_setting) { var addHtml = ""; if ( setting['mobilePosition'] == NAVIGLOBAL['MOBILE_POSITION']['RIGHT_BOTTOM'] ) { addHtml += cssNaviPrefix + ' { width: ' + setting['height'] + 'px; left: initial; right: 0px; height: ' + ((parseInt(setting['height']) + 8) * dragdrop.length) + 'px } '; addHtml += cssNaviPrefix + ' ul li.item { width: ' + setting['height'] + 'px; height: ' + (parseInt(setting['height']) + 8) + 'px; } '; addHtml += cssNaviPrefix + ' { top: ' + ((windowHeight - ((parseInt(setting['height']) + 8) * dragdrop.length)) / 2) + 'px; }'; addHtml += cssNaviPrefix + ' { border-radius: ' + setting['borderRadius'] + 'px 0px 0px ' + setting['borderRadius'] + 'px } '; addHtml += cssNaviPrefix + ' ul li ul.children { left: -201px; bottom: initial; margin-top: -' + (parseInt(setting['height']) + 8) + 'px; width: ' + VERTICAL_CHILDREN_WIDTH + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.10); } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) addHtml += cssNaviPrefix + ' ul li.item_primary > .inner { margin-top: 0px; margin-left: -8px } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['FLOATING']) { if (setting['bottomMargin'] != "") { addHtml += cssNaviPrefix + ' { right: ' + (parseInt(setting['bottomMargin'])) + 'px; } '; addHtml += cssNaviPrefix + ' { border-radius: ' + setting['borderRadius'] + 'px } '; } } addHtml += cssNaviPrefix + ' { top: initial; bottom: 24px; } '; if (isHadValue(setting['dividerColor'])) addHtml += cssNaviPrefix + ' ul li.item_divider { border-right: 0px; margin-right: 0px; border-bottom: solid 1px ' + setting['dividerColor'] + '; margin-bottom: -1px; } '; addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children {left: ' + (-(setting['submenuWidth']) - 1) + 'px; } '; addHtml += cssNaviPrefix + ' ul li.item { position: relative; } '; addHtml += cssNaviPrefix + ' ul li ul.children { margin-top: initial; bottom: 0px; top: initial; } '; /*if (setting['layout'] != NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) addHtml += cssNaviPrefix + ' ul li.item .inner { padding: 8px 0px 0px 0px; } ';*/ } return addHtml; }; var fixPositionLeftCenter = function (setting, cssNaviPrefix, dragdrop, section_setting) { var addHtml = ""; if (setting['mobilePosition'] == NAVIGLOBAL['MOBILE_POSITION']['LEFT_CENTER']) { addHtml += cssNaviPrefix + ' { width: ' + setting['height'] + 'px; right: initial; left: 0px; height: ' + ((parseInt(setting['height']) + 8) * dragdrop.length) + 'px } '; addHtml += cssNaviPrefix + ' ul li.item { width: ' + setting['height'] + 'px; height: ' + (parseInt(setting['height']) + 8) + 'px; } '; addHtml += cssNaviPrefix + ' { top: ' + ((windowHeight - ((parseInt(setting['height']) + 8) * dragdrop.length)) / 2) + 'px; }'; addHtml += cssNaviPrefix + ' { border-radius: 0px ' + setting['borderRadius'] + 'px ' + setting['borderRadius'] + 'px 0px } '; addHtml += cssNaviPrefix + ' ul li ul.children { left: ' + (parseInt(setting['height']) + 1) + 'px; bottom: initial; margin-top: -' + (parseInt(setting['height']) + 8) + 'px; width: ' + VERTICAL_CHILDREN_WIDTH + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.10); } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) addHtml += cssNaviPrefix + ' ul li.item_primary > .inner { margin-top: 0px; margin-left: 1px } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['FLOATING']) { if (setting['bottomMargin'] != "") { addHtml += cssNaviPrefix + ' { left: ' + (parseInt(setting['bottomMargin'])) + 'px; } '; addHtml += cssNaviPrefix + ' { border-radius: ' + setting['borderRadius'] + 'px } '; } } if (isHadValue(setting['dividerColor'])) addHtml += cssNaviPrefix + ' ul li.item_divider { border-right: 0px; margin-right: 0px; border-bottom: solid 1px ' + setting['dividerColor'] + '; margin-bottom: -1px; } '; addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; } '; /*if (setting['layout'] != NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) addHtml += cssNaviPrefix + ' ul li.item .inner { padding: 8px 0px 0px 0px; } ';*/ } return addHtml; }; var fixPositionLeftBottom = function (setting, cssNaviPrefix, dragdrop, section_setting) { var addHtml = ""; if (setting['mobilePosition'] == NAVIGLOBAL['MOBILE_POSITION']['LEFT_BOTTOM']) { addHtml += cssNaviPrefix + ' { width: ' + setting['height'] + 'px; right: initial; left: 0px; height: ' + ((parseInt(setting['height']) + 8) * dragdrop.length) + 'px } '; addHtml += cssNaviPrefix + ' ul li.item { width: ' + setting['height'] + 'px; height: ' + (parseInt(setting['height']) + 8) + 'px; } '; addHtml += cssNaviPrefix + ' { top: ' + ((windowHeight - ((parseInt(setting['height']) + 8) * dragdrop.length)) / 2) + 'px; }'; addHtml += cssNaviPrefix + ' { border-radius: 0px ' + setting['borderRadius'] + 'px ' + setting['borderRadius'] + 'px 0px } '; addHtml += cssNaviPrefix + ' ul li ul.children { left: ' + (parseInt(setting['height']) + 1) + 'px; bottom: initial; margin-top: -' + (parseInt(setting['height']) + 8) + 'px; width: ' + VERTICAL_CHILDREN_WIDTH + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.10); } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) addHtml += cssNaviPrefix + ' ul li.item_primary > .inner { margin-top: 0px; margin-left: 1px } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['FLOATING']) { if (setting['bottomMargin'] != "") { addHtml += cssNaviPrefix + ' { left: ' + (parseInt(setting['bottomMargin'])) + 'px; } '; addHtml += cssNaviPrefix + ' { border-radius: ' + setting['borderRadius'] + 'px } '; } } addHtml += cssNaviPrefix + ' { top: initial; bottom: 24px; } '; if (isHadValue(setting['dividerColor'])) addHtml += cssNaviPrefix + ' ul li.item_divider { border-right: 0px; margin-right: 0px; border-bottom: solid 1px ' + setting['dividerColor'] + '; margin-bottom: -1px; } '; addHtml += cssNaviPrefix + ' ul li ul.children {width: ' + setting['submenuWidth'] + 'px; } '; addHtml += cssNaviPrefix + ' ul li.item { position: relative; } '; addHtml += cssNaviPrefix + ' ul li ul.children { margin-top: initial; bottom: 0px; top: initial; } '; } return addHtml; }; let html = ' @media only screen and (max-width: 768px) {'; html += fixPositionBottom(setting, cssNaviPrefix, dragdrop, section_setting); html += fixPositionTop(setting, cssNaviPrefix, dragdrop, section_setting); html += fixPositionRightCenter(setting, cssNaviPrefix, dragdrop, section_setting); html += fixPositionRightBottom(setting, cssNaviPrefix, dragdrop, section_setting); html += fixPositionLeftCenter(setting, cssNaviPrefix, dragdrop, section_setting); html += fixPositionLeftBottom(setting, cssNaviPrefix, dragdrop, section_setting); html += '}'; return html; }; var Menu = Menu || {}; Menu.Section = Menu.Section || {}; /*************************************************************************************************************** Kiểm tra xem nếu section cấu hình margin thì trả về style ****************************************************************************************************************/ Menu.Section.getStyleSectionMargin = function(section_setting) { var embedMarginStyle = ""; if( section_setting["embed_margin"] != '0 0 0 0' && section_setting["embed_margin"].trim() != '' ) { var margin = Helper.HTML.parsePaddingMargin(section_setting["embed_margin"]); embedMarginStyle += ' margin: ' + margin.top + 'px ' + margin.right + 'px ' + margin.bottom + 'px ' + margin.left + 'px ' ; } return embedMarginStyle; }; /*********************************************************************************** Hàm này chỉ xử lý một case duy nhất là vừa khai báo section dạng sticky vừa chèn vào code, dẫn đến có 2 item xuất hiện đồng thời, khi đó ẩn cái sticky đi /*********************************************************************************** */ Menu.Section.hideDuplicateNavimanItems = function() { let navimanApp = document.querySelector("#naviman_app"); if (!navimanApp) return; // Thoát nếu không tìm thấy #naviman_app let naviItems = navimanApp.querySelectorAll(".naviItem"); let ids = new Set(); // Lấy danh sách ID từ các .naviItem trong #naviman_app naviItems.forEach(item => { let id = item.id; if (id) { ids.add(id); } }); // Kiểm tra xem ID có xuất hiện ở nơi khác không ids.forEach(id => { let allOccurrences = document.querySelectorAll(`.naviItem#${id}`); let outsideOccurrences = [...allOccurrences].filter(item => !navimanApp.contains(item)); if (outsideOccurrences.length > 0) { let itemInNavimanApp = navimanApp.querySelector(`.naviItem#${id} ul.navigation`); if (itemInNavimanApp) { itemInNavimanApp.style.display = "none"; // Ẩn ul.navigation nếu ID trùng ngoài #naviman_app } } }); }; /*************************************************************************************************************** Kiểm tra xem có phải được publish theo dạng publicToPlace không, nếu đúng trả về true ****************************************************************************************************************/ Menu.Section.checkPublicToPlace = function(naviItem ) { var isPublishToPlace = false; if (isHadValue(naviItem["data"]["setting"]['publishToPlaceDisplay'])) { if (naviItem["data"]["setting"]['publishToPlaceDisplay'] == "1") { isPublishToPlace = true; }else isPublishToPlace = false; // Sau bước này là có isPublishToPlace if( isPublishToPlace ) { if (isHadValue(naviItem["data"]["setting"]['publishToPlace'])) { var elsIdClass = naviItem["data"]["setting"]['publishToPlace']; if (elsIdClass && elsIdClass.trim() !== "") { isPublishToPlace = true; }else isPublishToPlace = false; } else isPublishToPlace = false; } } if (Helper.Env.isBackendMode()) isPublishToPlace = false; if( isPublishToPlace == true ) debugModeLog( naviItem["embed_id"] + " will publiced to place: " + naviItem["data"]["setting"]['publishToPlace'] ); return isPublishToPlace; }; /*************************************************************************************************************** Kiểm tra section được hiển thị dạng theme editor hay là publishToPlace ****************************************************************************************************************/ Menu.Section.checkSectionPublishWays = function (isDisplayed, naviItem, embed_id, isPublishToPlace) { if( isDisplayed == false ) return false; if( isDisplayed ) { var isSectionDisplay = false; // Trường hợp 1: có publishToPlace nhưng không có naviItem["embed_id"] -> Publish section qua publishToPlace if( isPublishToPlace && (naviItem["embed_id"] != embed_id) ) { isSectionDisplay = true; debugModeLog( '[Debugging] ' + naviItem["embed_id"] + " is shown by publishToPlace" ); } // Trường hợp 2: ko publishToPlace nhưng có naviItem["embed_id"] -> Publish section qua theme editor if( !isPublishToPlace && (naviItem["embed_id"] == embed_id) ) { isSectionDisplay = true; debugModeLog( '[Debugging] ' + naviItem["embed_id"] + " is shown by theme editor" ); } if( !isSectionDisplay ) isDisplayed = false; } return isDisplayed; }; /*************************************************************************************************************** Chỉnh CSS cho megamenu mobile ****************************************************************************************************************/ Menu.Section.fixCSS_Megamenu_Mobile = function(cssNaviPrefix, setting, dragdrop, isNaviSection, section_setting) { var addHtml = ""; addHtml += cssNaviPrefix + ' ul li ul.children { top: ' + parseInt(setting['height']) + 'px;} '; return addHtml; }; /*************************************************************************************************************** Chỉnh CSS cho megamenu desktop ****************************************************************************************************************/ Menu.Section.fixCSS_Megamenu_Desktop2 = function(cssNaviPrefix, setting, dragdrop, isNaviSection, section_setting, menuKind) { if( menuKind != NAVIGLOBAL['MENU_KINDS']['SECTION_DESKTOP_MEGAMENU'] ) return; var addHtml = ""; addHtml += cssNaviPrefix.trim() + '.SECTION_DESKTOP_MEGAMENU' + ' ul li ul.children { top: ' + parseInt(setting['height']) + 'px;} '; addHtml += cssNaviPrefix.trim() + '.SECTION_DESKTOP_MEGAMENU' + ' ul.children { width: ' + parseInt(setting['submenuWidth']) + 'px;} '; return addHtml; }; /*************************************************************************************************************** Hàm này không có tác dụng vì hiện tại cứ là section: display -> grid theo đó thì top/bottom không còn giá trị ****************************************************************************************************************/ Menu.Section.fixCSS_ResetBotomTop = function (naviman_appItem, shop, embed_id, section_setting) { //if(section_setting.length === 0 ) return; if(section_setting['embed_id'] == '') return; if(section_setting['not_sticky'] == false || section_setting['not_sticky'] == "false" ) return; Helper.HTML.addStyleToMenu(naviman_appItem, '#'+ embed_id +' { bottom: initial; top: initial; }'); }; /*************************************************************************************************************** Với megamenu thì đặt max-height: initial để hiển thị tất cả các menu con ****************************************************************************************************************/ Menu.Section.fixCSS_Megamenu_desktop = function (naviman_appItem, shop, embed_id, section_setting, menuKind) { if(section_setting['embed_id'] == '') return; if(section_setting['not_sticky'] == false || section_setting['not_sticky'] == "false" ) return; if( menuKind != NAVIGLOBAL['MENU_KINDS']['SECTION_DESKTOP_MEGAMENU'] ) return; Helper.HTML.addStyleToMenu(naviman_appItem, '#'+ embed_id + ' ul li ul.children { max-height: initial; } '); }; /*************************************************************************************************************** Tìm đến section cha của một element ****************************************************************************************************************/ Menu.Section.getSessionParent = function(session_parent) { var limitCount = 0; while( true ) { limitCount ++; if( limitCount >= 30 ) return null; if( session_parent.nodeName == "SECTION" ) return session_parent; if( session_parent.nodeName == "MAIN" ) return null; if( session_parent == document.body) return null; session_parent = session_parent.parentElement; } }; /*************************************************************************************************************** Tìm đến shopify-block cha của một element ****************************************************************************************************************/ Menu.Section.getBlockParent = function(session_parent) { var limitCount = 0; while( true ) { limitCount ++; if( limitCount >= 30 ) return null; if( session_parent.className.includes("shopify-block") ) return session_parent; if( session_parent.nodeName == "MAIN" ) return null; if( session_parent == document.body) return null; session_parent = session_parent.parentElement; } }; /*************************************************************************************************************** Tìm đến page-width cha của một element ****************************************************************************************************************/ Menu.Section.getPageWidthParent = function(session_parent) { var limitCount = 0; while( true ) { limitCount ++; if( limitCount >= 30 ) return null; if( session_parent.className.includes("page-width") ) return session_parent; if( session_parent.nodeName == "MAIN" ) return null; if( session_parent == document.body) return null; session_parent = session_parent.parentElement; } }; /*************************************************************************************************************** Căn chỉnh CSS cho section parent, để hiển thị tốt hơn ****************************************************************************************************************/ Menu.Section.fixCSS_SectionParent = function (naviman_app, naviItem, embed_id, section_setting, menuKind) { var setting = naviItem["data"]["setting"]; var session = Menu.Section.getSessionParent(naviman_app); if( session != null ) { session.style.position = "relative"; /* Fix cho phần header trên desktop, setup màu, bóng.. cho Section thay vì riêng cái menu đó *****/ if( menuKind == NAVIGLOBAL['MENU_KINDS']['SECTION_DESKTOP_MEGAMENU'] ) { session.style.backgroundColor = setting['backgroundColor']; if( setting['level1BackgroundHide'] == false ) { session.style.boxShadow = "0px 4px 8px 0px rgba(0, 0, 0, 0.05)"; document.getElementById(embed_id).style.boxShadow = "initial"; } } /* Fix việc không bị đè các item này lên item khác *****/ var zIndex = (50 - 1); if (isHadValue(setting['zIndex'])) zIndex = setting['zIndex'] - 1; session.style.zIndex = zIndex; if( setting['fixedTopScrolling'] == true || setting['fixedTopScrolling'] == "true" ) { session.style.position = "sticky"; session.style.top = 0; if( setting["level1Dropshadow"] == false || setting["level1Dropshadow"] == 'false' ) { var stickyPageYOffset = session.offsetTop; window.onscroll = function () { if (window.pageYOffset > stickyPageYOffset) { session.style.boxShadow = "0px 4px 8px 0px rgba(0, 0, 0, 0.05)"; } else { session.style.boxShadow = "initial"; } }; } } } var shopify_block = Menu.Section.getBlockParent(naviman_app); if( shopify_block != null ) { shopify_block.style.display = "flex"; } // Nếu full width thì bỏ padding 2 bên đi if( section_setting['embed_is_full'] == true || section_setting['embed_is_full'] == "true" ) { var page_width = Menu.Section.getPageWidthParent(naviman_app); if (page_width != null) { page_width.style.padding = "0px"; } } }; Menu.Section.fixWidthLayoutForMegamenu = function (itemExtWidth, menuKind) { if( menuKind == NAVIGLOBAL['MENU_KINDS']['SECTION_DESKTOP_MEGAMENU'] || menuKind == NAVIGLOBAL['MENU_KINDS']['SECTION_MOBILE_MEGAMENU']) { if( itemExtWidth.width == "" ) // Với mega menu thì level 1: Auto -> Hug itemExtWidth = { 'width': 'auto', 'style' : ' width: auto ', 'class' : '' }; } return itemExtWidth; }; Menu.Section.fixMobileMegamenuScrollPosition = function(menuItem) { if (!menuItem || !(menuItem instanceof Element)) { console.warn('[fixMegamenu] menuItem không hợp lệ:', menuItem); return; } const submenu = menuItem.querySelector('ul.children[menulevel="2"]'); if (!submenu) return; const computed = window.getComputedStyle(submenu); if (computed.position !== 'fixed') return; const rect = menuItem.getBoundingClientRect(); submenu.style.top = `${rect.bottom + 1}px`; }; var Menu = Menu || {}; Menu.Context = Menu.Context || {}; Menu.Context.checkTriggerIDClass = function(isDisplayed, naviItem ) { if (isHadValue(naviItem["data"]["setting"]['publishTriggerIDClass'])) { var elsArray = Helper.String.stringToArray( naviItem["data"]["setting"]['publishTriggerIDClass'] ); elsArray.forEach(function(elsIdClass, index) { console.log(naviItem["embed_id"] + " added trigger event to: " + elsIdClass); var els = document.querySelectorAll(elsIdClass); els.forEach(function(el) { const newEl = removeAllEventListeners(el); newEl.addEventListener("click", function(event) { if (newEl.tagName.toLowerCase() === "a") { event.preventDefault(); // chặn chuyển hướng link } openNaviMenu(naviItem["embed_id"]); }, false); }); }); } debugModeLog( naviItem["embed_id"] + " is always shown. The cause is: CONTEXT_SLIDE" ); } Menu.Context.isDisplayTrigger = function (menuKindClass, naviItem) { if (menuKindClass != "CONTEXT_SLIDE") return false; var data = naviItem["data"]; if(typeof data["setting"]["displayTrigger"] == 'undefined') return false; if (data["setting"]["displayTrigger"] == 1 || data["setting"]["displayTrigger"] == "1" ) { return true; } return false; }; Menu.Context.splitTriggerFunction = function(str) { // Sử dụng regex để tách tên hàm và biến const regex = /(\w+)\((.+)\)/; const match = str.match(regex); if (match) { const functionName = match[1]; // Tên hàm const variableName = match[2]; // Tên biến return { functionName, variableName }; } else { return null; // Nếu chuỗi không hợp lệ } }; Menu.Context.generateCSS_FixForHambuger = function (idCssNaviPrefix, setting, dragdrop, isNaviSection, section_setting, embed_id, naviman_appItem, menuKind) { var addHtml = " "; if( menuKind != NAVIGLOBAL['MENU_KINDS']['CONTEXT_SLIDE'] ) return; var isOnMobile = (window.innerWidth <= 768); if (isHadValue(setting['submenuBackgroundColor'])) addHtml += idCssNaviPrefix + ' ul.children { background: ' + setting['submenuBackgroundColor'] + '; } '; if (isHadValue(setting['submenuDividerColor'])) addHtml += idCssNaviPrefix + ' ul.children ul.children { border-color: ' + setting['submenuDividerColor'] + '; } '; // Fix arrow icons to center of menu item (dynamic -> fixing) setTimeout(function(){ const div = document.querySelector(idCssNaviPrefix + ' ul > li.is-parent-top > .inner'); if( div != null ) { var html = ''; naviman_appItem.insertAdjacentHTML('beforebegin', html); } }, 1000); // Lưu vào biến window về hamburgerSubDirection để dùng trong hàm showLevel2Items nhằm reset all sub menus ----------------------- if (!window.hamburgerSubDirection) window.hamburgerSubDirection = {}; window.hamburgerSubDirection[embed_id] = setting["hamburgerSubDirection"]; // Trên desktop mở menu ra ngoài thay vì xổ xuống if( !isOnMobile ) { // Desktop only if (setting["hamburgerSubDirection"] == 2) { // Xác định vị trí hamburger: 1 = trái, 2 = phải (mặc định là 1) let hamburgerPosition = 1; if (setting["hamburgerPosition"] != null) { hamburgerPosition = parseInt(setting["hamburgerPosition"]); if (hamburgerPosition !== 2) hamburgerPosition = 1; } const parentMenuSize = getHiddenDivSize(document.querySelector(idCssNaviPrefix)); addHtml += `${idCssNaviPrefix} ul li.item > ul.children { position: fixed; top: 0px; height: 100% !important; border: 0px; margin-top: 0px; border-radius: 0px; ${hamburgerPosition === 2 ? 'border-right: solid 1px rgba(128,128,128,0.2); right: ' + parentMenuSize.width + 'px; left: initial;' : 'border-left: solid 1px rgba(128,128,128,0.2); left: ' + parentMenuSize.width + 'px;'} width: ${parentMenuSize.width}px; }`; // Chỉnh arrow addHtml += `${idCssNaviPrefix} ul > li.is-parent-top ul li.is-parent::after { right: 8px; top: 16px; }`; } } return addHtml; }; var Menu = Menu || {}; Menu.Item = Menu.Item || {}; Menu.Item.isItemPublished = function( item ) { var itemIsPublished = getItemValue(item, "ispublished", 1); var itemHideWhenLogined = getItemValue(item, "hidewhenlogined", 0); var itemShowWhenLogined = getItemValue(item, "showwhenlogined", 0); if( itemIsPublished == 0 ) return false; if( itemHideWhenLogined == 1 ) { if( isUserLoggedIn() ) return false; } if( itemShowWhenLogined == 1 ) { if( !(isUserLoggedIn()) ) return false; } var hidePages = Menu.Item.getHidePages(parseAttributes(decodeQuery( item['attr'] ))); if( hidePages.length != 0 ) { let currentTemplate = getCurrentTemplate(); if (hidePages.includes(currentTemplate)) return false; } return true; }; Menu.Item.getHidePages = function(attrArray) { if (!Array.isArray(attrArray) || attrArray.length === 0) return []; // Kiểm tra đầu vào hợp lệ for (const attr of attrArray) { let [key, value] = attr.split("=").map(s => s.trim()); // Cắt khoảng trắng if (key === "hidepages") { return value && value.trim() ? value.split("|").map(s => s.trim()) : []; } } return []; // Không tìm thấy "hidepages" }; var generateCSS_init = function ( setting ) { //debugConsole("1.generateCSS_init"); setting['submenuWidth'] = defaultValue(setting['submenuWidth'], 200); setting['submenuFullExpandWidth'] = defaultValue(setting['submenuFullExpandWidth'], ""); if (window.innerWidth < parseInt(setting['submenuFullExpandWidth'])) setting['submenuFullExpandWidth'] = ""; setting['textSize'] = defaultValue( setting['textSize'], 10); setting['spaceTextIcon'] = defaultValue(setting['spaceTextIcon'], 2); setting['iconSize'] = defaultValue(setting['iconSize'], DEFAULT_ICON_IMAGE_SIZE); setting['imageRadius'] = defaultValue(setting['imageRadius'], 0); setting['height'] = defaultValue(setting['height'], 54); setting['borderRadius'] = defaultValue(setting['borderRadius'], 0); setting['opacity'] = defaultValue(setting['opacity'], 100); setting['bottomMargin'] = defaultValue(setting['bottomMargin'], ""); setting['settingMargin'] = defaultMarginPadding( setting['settingMargin'] ); setting['settingPadding'] = defaultMarginPadding( setting['settingPadding'] ); }; var generateCSS_UI_Level1_Menuitems = function ( setting, cssNaviPrefix, naviman_appItem, dragdrop, section_setting ) { //debugConsole("2.generateCSS_UI_Level1_Menuitems"); var isOnMobile = window.innerWidth <= 768; var addHtml = ""; if (isHadValue(setting['textColor'])) { addHtml += cssNaviPrefix + ' ul li.item .name { color: ' + setting['textColor'] + '; } '; addHtml += cssNaviPrefix + ' ul li.item .description { color: ' + setting['textColor'] + '; } '; } // TODO: Cho chọn không chọn font và một font tự chọn tên. if (isHadValue(setting['fontFamily'])) { if( setting['fontFamily'] != "Use+Default" ) { let fontFamily_css = ''; naviman_appItem.insertAdjacentHTML('beforebegin', fontFamily_css); addHtml += cssNaviPrefix + ' {font-family: "' + setting['fontFamily'].strReplace('+', ' ') + '", "Roboto"} '; } } if (isHadValue(setting['textSize'])) { addHtml += cssNaviPrefix + ' ul li.item > .inner .name { font-size: ' + setting['textSize'] + 'px; } '; addHtml += cssNaviPrefix + ' ul li.item > .inner .name > { font-size: ' + setting['textSize'] + 'px; } '; // Sửa chỗ này để overwrite các ông khác. } /* if (isHadValue(setting['spaceTextIcon']))*/ /* addHtml += cssNaviPrefix + ' ul li.item .icon, ' + cssNaviPrefix + ' ul li.item .image { height: ' + (21 + (setting['spaceTextIcon'] - 2)) + 'px; } ';*/ if (isHadValue(setting['dividerColor'])) addHtml += cssNaviPrefix + ' ul li.item_divider { border-color: ' + setting['dividerColor'] + '; } '; if (isHadValue(setting['badgeColor'])) addHtml += cssNaviPrefix + 'ul li.item_badge .inner .icon::before, ' + cssNaviPrefix + ' ul li.item_badge .inner .image::before { color: ' + setting['badgeColor'] + '; } '; if (isHadValue(setting['iconColor'])) addHtml += cssNaviPrefix + 'ul li.item .icon i { color: ' + setting['iconColor'] + '; } '; if (isHadValue(setting['iconSize'])) { /* Login của đoạn này như sau (Chỉ áp dụng cho icon/Small image): 1. Nếu setting chung icon size thì áp dụng cho cả icon và image 2. Đối với level 2: Thì đặt chiều cao của icon và image bằng nhau và bằng iconSize + 4 */ addHtml += cssNaviPrefix + 'ul li.item .icon i { font-size: ' + setting['iconSize'] + 'px; } '; addHtml += cssNaviPrefix + 'ul li.item ul li.child .icon i { font-size: ' + setting['iconSize'] + 'px; } '; addHtml += cssNaviPrefix + 'ul li.item ul li.child .icon { height: ' + ( parseInt(setting['iconSize']) + 4) + 'px; } '; addHtml += cssNaviPrefix + 'ul li.item ul li.child .info { width: calc(100% - ' + parseInt(setting['iconSize']) + 'px); } '; addHtml += cssNaviPrefix + 'ul li.item .image img { height: ' + setting['iconSize'] + 'px; } '; addHtml += cssNaviPrefix + 'ul li.item ul li.child .image img { height: ' + setting['iconSize'] + 'px; } '; addHtml += cssNaviPrefix + 'ul li.item ul li.child .image { height: ' + ( parseInt(setting['iconSize']) + 4) + 'px; } '; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) addHtml += cssNaviPrefix + ' ul li.item_primary > .inner { left: calc(50% - 26px); position: absolute; padding-top: ' + (16 - (setting['iconSize'] - 12) / 2) + 'px; } '; } // Don't display text --------------------------------------------------------- if (setting['textHide'] == "true" || setting['textHide'] == true) { addHtml += cssNaviPrefix + ' ul li.item > .inner .name { display:none; } '; addHtml += cssNaviPrefix + ' ul li.item > .inner .description { display:none; } '; /* if (setting['layout'] != NAVIGLOBAL['LAYOUT']['FAB']) addHtml += cssNaviPrefix + 'ul li.item .inner { padding-top: ' + ((setting['height'] - 50) / 2 + 8 + (setting['textSize'] / 2)) + 'px } '; */ if (setting['layout'] != NAVIGLOBAL['LAYOUT']['FAB']) { let isVertical = false; if (isOnMobile) if (setting['mobilePosition'] == NAVIGLOBAL['MOBILE_POSITION']['RIGHT_CENTER'] || setting['mobilePosition'] == NAVIGLOBAL['MOBILE_POSITION']['LEFT_CENTER'] || setting['mobilePosition'] == NAVIGLOBAL['MOBILE_POSITION']['RIGHT_BOTTOM'] || setting['mobilePosition'] == NAVIGLOBAL['MOBILE_POSITION']['LEFT_BOTTOM'] ) isVertical = true; if (!isOnMobile) // Desktop mode if (setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['RIGHT_TOP'] || setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['LEFT_TOP'] || setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['LEFT_FULL_TOP'] || setting['desktopPosition'] == NAVIGLOBAL['DESKTOP_POSITION']['LEFT_FULL_CENTER'] ) isVertical = true; if (isVertical) { let itemHeight = (parseInt(setting['height']) - setting['textSize']); /* TODO: Cần chỉnh chỗ này, nếu như có padding thì phải phình to ra chứ? */ addHtml += cssNaviPrefix + ' ul li.item { height: ' + itemHeight + 'px } '; addHtml += cssNaviPrefix + '{ height: ' + itemHeight * dragdrop.length + 'px } '; } } } return addHtml; } var generateCSS_UI_Level1_Background = function ( setting, cssNaviPrefix, section_setting, menuKind ) { var addHtml = ""; // Expand menu icon (only mega menu and slide) --------------------------------------------------------- var embed_id = cssNaviPrefix.trim(); var embed_id = embed_id.startsWith(".") ? embed_id.slice(1) : embed_id; addHtml += Menu.Common.Level1.generateExpandArrowShow( setting, cssNaviPrefix, menuKind ); addHtml += Menu.Common.Level1.generateBackground( setting, cssNaviPrefix, menuKind ); addHtml += Menu.Common.Level1.generateDropshadow( setting, cssNaviPrefix, menuKind ); addHtml += Menu.Common.Level1.generateHeight( setting, cssNaviPrefix, menuKind ); addHtml += Menu.Common.Level1.generateBorderRadius( setting, cssNaviPrefix, menuKind ); addHtml += Menu.Common.Level1.generateOpacity( setting, cssNaviPrefix, menuKind ); return addHtml; }; var generateCSS_UI_Level2 = function ( setting, cssNaviPrefix, naviman_appItem, dragdrop, section_setting ) { //debugConsole("5.generateCSS_UI_Level2"); var addHtml = ""; if (isHadValue(setting['submenuTextColor'])) { addHtml += cssNaviPrefix + ' ul li.item ul li.child .name { color: ' + setting['submenuTextColor'] + '; } '; addHtml += cssNaviPrefix + ' ul li.item a { color: ' + setting['submenuTextColor'] + '; } '; addHtml += cssNaviPrefix + ' ul li.item ul li.child .description { color: ' + setting['submenuTextColor'] + '; } '; addHtml += cssNaviPrefix + ' ul li ul.children .overlay b.close { color: ' + setting['submenuTextColor'] + '; } '; } if (isHadValue(setting['submenuIconColor'])) addHtml += cssNaviPrefix + ' ul li.item ul li.child .icon i { color: ' + setting['submenuIconColor'] + '; } '; if (isSettingBeTrue(setting['level2BackgroundHide'])) { // Nếu không có nền thì bỏ nền và bỏ bóng. addHtml += cssNaviPrefix + ' ul li ul.children { background: initial; } '; addHtml += cssNaviPrefix + ' ul li ul.children { box-shadow: none !important; } '; }else { if (isHadValue(setting['submenuBackgroundColor'])) { addHtml += cssNaviPrefix + ' ul li ul.children { background: ' + setting['submenuBackgroundColor'] + ' } '; addHtml += cssNaviPrefix + ' ul li ul.children .overlay b.close { background: ' + setting['submenuBackgroundColor'] + ' } '; } } if (! isSettingBeTrue(setting['level2Dropshadow'], true)) { // Nếu không có nền thì bỏ nền và bỏ bóng. addHtml += cssNaviPrefix + ' ul li ul.children { box-shadow: none !important; } '; } if (isHadValue(setting['submenuDividerColor'])) addHtml += cssNaviPrefix + ' ul li.child_divider { border-color: ' + setting['submenuDividerColor'] + '; } '; return addHtml; }; var generateCSS_Publish = function (setting, cssNaviPrefix, section_setting) { //debugConsole("7.generateCSS_Publish"); var isOnMobile = window.innerWidth <= 768; var addHtml = ""; addHtml += ' @media only screen and (max-width: 768px) { '; if (setting['mobileDisplay'] == "false" || setting['mobileDisplay'] == false) addHtml += cssNaviPrefix + ' { display: none !important; } '; if( !isOnMobile ) addHtml += cssNaviPrefix + ' { display: none !important; } '; addHtml += ' } '; addHtml += ' @media only screen and (min-width: 769px) { '; if (setting['desktopDisplay'] == "false" || setting['desktopDisplay'] == false) { addHtml += cssNaviPrefix + ' { display: none !important; } '; } if( isOnMobile ) addHtml += cssNaviPrefix + ' { display: none !important; } '; addHtml += ' } '; return addHtml; }; var generateCSS_Position = function (setting, cssNaviPrefix, section_setting, menuKind) { var addHtml = ""; addHtml += ' @media only screen and (max-width: 768px) {'; if (setting['mobileAutoHide'] == "true" || setting['mobileAutoHide'] == true) { if (setting['mobileDisplay'] == "true" || setting['mobileDisplay'] == true) scrollToHide("mobile", cssNaviPrefix); } if (setting['mobileAutoShow'] == "true" || setting['mobileAutoShow'] == true) { if (setting['mobileDisplay'] == "true" || setting['mobileDisplay'] == true) scrollToShow("mobile", cssNaviPrefix); } addHtml += '} '; addHtml += ' @media only screen and (min-width: 769px) {'; if (setting['desktopAutoHide'] == "true" || setting['desktopAutoHide'] == true) { if( setting['desktopDisplay'] == "true" || setting['desktopDisplay'] == true ) if( menuKind == NAVIGLOBAL['MENU_KINDS']['STICKY_TABBAR']) { if (setting['desktopPosition'] != NAVIGLOBAL['DESKTOP_POSITION']['LEFT_FULL_TOP'] && setting['desktopPosition'] != NAVIGLOBAL['DESKTOP_POSITION']['LEFT_FULL_CENTER'] && setting['desktopPosition'] != NAVIGLOBAL['DESKTOP_POSITION']['RIGHT_FULL_TOP'] && setting['desktopPosition'] != NAVIGLOBAL['DESKTOP_POSITION']['RIGHT_FULL_CENTER'] ) scrollToHide("desktop", cssNaviPrefix); } if( menuKind == NAVIGLOBAL['MENU_KINDS']['STICKY_FAB_SUPPORT']) scrollToHide("desktop", cssNaviPrefix); } if (setting['desktopAutoShow'] == "true" || setting['desktopAutoShow'] == true) { if( setting['desktopDisplay'] == "true" || setting['desktopDisplay'] == true ) if( menuKind == NAVIGLOBAL['MENU_KINDS']['STICKY_TABBAR']) { if (setting['desktopPosition'] != NAVIGLOBAL['DESKTOP_POSITION']['LEFT_FULL_TOP'] && setting['desktopPosition'] != NAVIGLOBAL['DESKTOP_POSITION']['LEFT_FULL_CENTER'] && setting['desktopPosition'] != NAVIGLOBAL['DESKTOP_POSITION']['RIGHT_FULL_TOP'] && setting['desktopPosition'] != NAVIGLOBAL['DESKTOP_POSITION']['RIGHT_FULL_CENTER'] ) scrollToShow("desktop", cssNaviPrefix); } if( menuKind == NAVIGLOBAL['MENU_KINDS']['STICKY_FAB_SUPPORT']) scrollToShow("desktop", cssNaviPrefix); } addHtml += '} '; return addHtml; }; var generateCSS_Advance = function (setting, cssNaviPrefix, naviman_appItem, embed_id, section_setting) { //debugConsole("9.generateCSS_Advance"); var addHtml = ""; // Global JS / jQuery --------------------------------------------------------- var jsScript = document.createElement('script'); jsScript.textContent = Helper.HTML.clearCSS_JS(setting['jsCode']); document.body.appendChild(jsScript); var jsNaviScript = document.createElement('script'); jsNaviScript.textContent = standardizeFunctionString( Helper.HTML.clearCSS_JS(setting['jsNaviCode']) ); document.body.appendChild(jsNaviScript); // CSS --------------------------------------------------------- naviman_appItem.insertAdjacentHTML('beforebegin', ''); naviman_appItem.insertAdjacentHTML('beforebegin', ''); // zIndex ------------------------------------------------------ if (isHadValue(setting['zIndex'])) addHtml += cssNaviPrefix + ' { z-index: '+ setting['zIndex'] +'; } '; return addHtml; }; var generateCSS_FixByLayout = function (setting, cssNaviPrefix, dragdrop, section_setting) { //debugConsole("6.generateCSS_FixByLayout"); var addHtml = ""; if (setting['layout'] == NAVIGLOBAL['LAYOUT']['HIGHLIGHT']) { if (setting['highlightColor'].trim() != "") addHtml += cssNaviPrefix + ' ul li.item_primary > .inner { background: ' + setting['highlightColor'] + '; } '; if (setting['highlightIconColor'].trim() != "") addHtml += cssNaviPrefix + ' ul li.item_primary > .inner i { color: ' + setting['highlightIconColor'] + '; } '; } if (setting['layout'] == NAVIGLOBAL['LAYOUT']['FLOATING']) { if (setting['bottomMargin'] != "") { addHtml += cssNaviPrefix + ' { bottom: ' + setting['bottomMargin'] + 'px; } '; } } if (setting['layout'] == NAVIGLOBAL['LAYOUT']['FAB']) { addHtml += cssNaviPrefix + ' { width: ' + setting['height'] + 'px; left: initial; right: 16px; height: ' + parseInt(setting['height']) + 'px; width: ' + (parseInt(setting['height']) * dragdrop.length) + 'px; } '; //addHtml += cssNaviPrefix + ' ul li.item .inner { padding: 8px 0px 0px 0px; } '; //addHtml += cssNaviPrefix + 'ul li.item .inner { padding-top: ' + ((setting['height'] - 50) / 2 + 8 + (setting['textSize'] / 2)) + 'px } '; addHtml += cssNaviPrefix + ' ul li ul.children { left: initial; right: 0px; bottom: 4px; width: ' + setting['submenuWidth'] + 'px; } '; addHtml += cssNaviPrefix + ' ul li ul.children { ' + BOX_SHADOW + ';} '; if (setting['bottomMargin'] != "") addHtml += cssNaviPrefix + ' { bottom: ' + (parseInt(setting['bottomMargin'])) + 'px; } '; } return addHtml; } var generateCSS_UI_Common = function ( setting, cssNaviPrefix, naviman_appItem, dragdrop, section_setting ) { var addHtml = ""; // Logic: Nếu set height và kiểu left-right thì sẽ đặt một cái padding-top để nó căn vào giữa cho nó đẹp. //addHtml += cssNaviPrefix + ' ul > li.item .inner { padding-top: ' + ((setting['height'] - 50) / 2 + 7) + 'px } '; //addHtml += cssNaviPrefix + ' ul > li.left-right .inner { padding-top: 0px } '; // TODO: Chỗ này chưa ngon do nếu gap < 0 thì chỉ sống với top-down if (isHadValue(setting['spaceTextIcon'])) { if( setting['spaceTextIcon'] < 0 ) { addHtml += cssNaviPrefix + ' ul li.item .inner { gap: 0px }'; addHtml += cssNaviPrefix + ' ul li.item .inner .info { margin-top: '+ setting['spaceTextIcon'] +'px }'; }else addHtml += cssNaviPrefix + ' ul li.item .inner { gap: '+ setting['spaceTextIcon'] +'px }'; } if (isHadValue(setting['imageRadius'])) { addHtml += cssNaviPrefix + ' li.item .image img { border-radius: '+ setting['imageRadius'] +'px !important; } '; } if( isUserLoggedIn() ) { addHtml += cssNaviPrefix + ' ul li.publish-show-logined { display: -webkit-inline-box }'; addHtml += cssNaviPrefix + ' ul li.publish-hide-logined { display: none }'; }else { addHtml += cssNaviPrefix + ' ul li.publish-show-logined { display: none }'; addHtml += cssNaviPrefix + ' ul li.publish-hide-logined { display: -webkit-inline-box }'; } return addHtml; } var getItemValue = function( item, keyName, defaultVal ) { if( item[keyName] != null ) return item[keyName]; return defaultVal; } var generateCSS_Level1_Width = function (setting, cssNaviPrefix, naviman_appItem, dragdrop, section_setting) { var addHtml = ""; var fixPx = 0; var fixPercent = 0; var automationCount = 0; var maxAutomationCount = 0; dragdrop.forEach((item) => { if( Menu.Item.isItemPublished(item) == false ) return; var itemWidthLayout = getItemValue(item, "widthlayout", 1); if( itemWidthLayout == 14 ) fixPx += parseInt( item["widthfix"] ); if( itemWidthLayout == 2 ) fixPercent += 8.3333333333; if( itemWidthLayout == 3 ) fixPercent += 16.6666666666; if( itemWidthLayout == 4 ) fixPercent += 25; if( itemWidthLayout == 5 ) fixPercent += 33.3333333333; if( itemWidthLayout == 6 ) fixPercent += 41.6666666666; if( itemWidthLayout == 7 ) fixPercent += 50; if( itemWidthLayout == 8 ) fixPercent += 58.3333333333; if( itemWidthLayout == 9 ) fixPercent += 66.6666666666; if( itemWidthLayout == 10 ) fixPercent += 75; if( itemWidthLayout == 11 ) fixPercent += 83.3333333333; if( itemWidthLayout == 12 ) fixPercent += 91.6666666666; if( itemWidthLayout == 13 ) fixPercent += 100; if( itemWidthLayout == 15 ) fixPercent += 10; if( itemWidthLayout == 16 ) fixPercent += 20; if( itemWidthLayout == 17 ) fixPercent += 50; if( itemWidthLayout == 18 ) fixPercent += 100; if( itemWidthLayout == 20 ) { // Do nothing } if( itemWidthLayout == 1 ) automationCount ++; if( fixPercent == 100 ) { // Nếu gặp một item tràn màn hình thì ngắt, lấy max để làm lưới cơ sở. if( automationCount > maxAutomationCount) { maxAutomationCount = automationCount; automationCount = 0; } } }); if( automationCount == 0 && maxAutomationCount == 0 ) return ""; if( maxAutomationCount > 0 ) automationCount = maxAutomationCount; if( fixPercent >= 100 ) fixPercent = 0; addHtml += cssNaviPrefix + ' ul li.item { width: calc( calc( '+ (100 - fixPercent ) +'% - '+ fixPx +'px) / '+ automationCount +') } '; return addHtml; } var generateCSS = function(naviman_appItem, embed_id, setting, dragdrop, isNaviSection, section_setting, menuKind) { generateCSS_init(setting); let html = ''; naviman_appItem.insertAdjacentHTML('beforebegin', html); /*debugConsole("R:Setting ----------------------------"); debugConsole(setting);*/ }; Helper.Env.checkBrowserSupport(); Helper.Debug.welcomeScreen(); var init = function () { // debugConsole(NAVIGLOBAL); }; var addNaviItemToQueue = function(naviItem) { const exists = window.navimanData.some(item => item.embed_id === naviItem.embed_id); if (!exists) { window.navimanData.push(naviItem); } else { console.log(`naviItem with embed_id ${naviItem.embed_id} already exists in queue.`); } }; /*************************************************************************************************************** Nhận về một đoạn giống như trong Blocks, có 2 trường hợp; 1. Nếu embed_id == "" -> Chèn kiểu Alls (sticky, context, section to place), vẽ vào #naviman_app 2. Nếu embed_id != "" -> Chèn kiểu section qua Theme Editor, vẽ vào embed_id + "-container" ****************************************************************************************************************/ var drawBottomNav = function (response, naviman_domain, var_shop, var_embed_id, section_setting = [], fixMenuKind = 0) { var shop = var_shop; var embed_id = var_embed_id; // Nếu ở dạng sticky thì sử dụng thẻ chung: