import { getCacheFor } from './responsive-desktop-menu' const getItemWidthsFrom = (container) => [...container.querySelectorAll('[data-items] > [data-id]')] .filter((el) => el.dataset.id.indexOf('menu') === -1) .reduce((sum, el) => { let style = window.getComputedStyle(el) return ( sum + el.getBoundingClientRect().width + parseInt(style.getPropertyValue('margin-left')) + parseInt(style.getPropertyValue('margin-right')) ) }, 0) const getTotalItemsWidthFor = (nav) => { let navStyle = window.getComputedStyle(nav) return ( getCacheFor(nav.__id).itemsWidth.reduce((sum, n) => sum + n, 0) + (parseInt(navStyle.getPropertyValue('margin-left')) + parseInt(navStyle.getPropertyValue('margin-right'))) ) } /** * 1. Nav is in side with NO items in middle * 2. Nav is in middle * 3. Nav is either: * a. Secondary * b. Side, but with middle */ const computeAvailableSpaceFor = (nav) => { let baseContainer = nav.closest('[class*="ct-container"]') const baseContainerStyle = window.getComputedStyle(baseContainer) let baseWidth = baseContainer.getBoundingClientRect().width baseWidth -= parseInt(baseContainerStyle.getPropertyValue('padding-left')) + parseInt(baseContainerStyle.getPropertyValue('padding-right')) // side | middle | secondary // TODO: compute sides let closestColumn = nav.closest('[data-column]').dataset.column let navSide = closestColumn === 'start' || closestColumn === 'end' ? 'side' : closestColumn === 'middle' ? 'middle' : 'secondary' let hasMiddle = baseContainer.querySelector('[data-column="middle"]') // Case 1 if (navSide === 'side' && !hasMiddle) { let allNavs = baseContainer.querySelectorAll('[data-id*="menu"]') let containerWidth = baseWidth - getItemWidthsFrom(baseContainer) if (allNavs.length > 1) { const totalItemsWidth = getTotalItemsWidthFor(nav) const totalItemsWidthFromAllNavs = [...allNavs].reduce( (total, nav) => total + getTotalItemsWidthFor(nav), 0 ) containerWidth *= (100 * totalItemsWidth) / totalItemsWidthFromAllNavs / 100 } return containerWidth } if (navSide === 'middle') { return ( baseWidth - Math.max( baseContainer.querySelector('[data-column="start"]') ? getItemWidthsFrom( baseContainer.querySelector('[data-column="start"]') ) : 0, baseContainer.querySelector('[data-column="end"]') ? getItemWidthsFrom( baseContainer.querySelector('[data-column="end"]') ) : 0 ) * 2 ) } return ( (baseWidth - (baseContainer.querySelector('[data-column="middle"]') ? getItemWidthsFrom( baseContainer.querySelector('[data-column="middle"]') ) : 0)) / 2 - getItemWidthsFrom(nav.closest('[data-column]')) ) } export const getItemsDistribution = (nav) => { let containerWidth = computeAvailableSpaceFor(nav) let baseContainer = nav.closest('[class*="ct-container"]') let navStyle = window.getComputedStyle(nav) const totalItemsWidth = getTotalItemsWidthFor(nav) const navSideMargins = parseInt(navStyle.getPropertyValue('margin-left')) + parseInt(navStyle.getPropertyValue('margin-right')) const hasAnyOverlap = totalItemsWidth > containerWidth - navSideMargins if (!hasAnyOverlap) { return { fit: getCacheFor(nav.__id).children, notFit: [], } } let allNavs = baseContainer.querySelectorAll('[data-id*="menu"]') const itemsWidth = getCacheFor(nav.__id).itemsWidth const availableSpaceForItems = containerWidth - navSideMargins const moreItemWidth = getCacheFor(nav.__id).moreItemWidth const itemsWithWidths = getCacheFor(nav.__id) .children.map((el, index) => { return { el, width: itemsWidth[index], } }) .reduce((result, item) => { if (result.length === 0) { return [item] } return [ ...result, { ...item, width: item.width + result[result.length - 1].width, }, ] }, []) let itemsThatFit = itemsWithWidths.filter((itemWithWidth) => { return itemWithWidth.width + moreItemWidth < availableSpaceForItems }) // Special case: if no items fit, but the first item is smaller than the more item, show it // This prevents showing only the "More" item with no siblings. if ( itemsThatFit.length === 0 && itemsWithWidths.length > 0 && itemsWithWidths[0].width < moreItemWidth ) { itemsThatFit = [itemsWithWidths[0]] } const elsThatFit = itemsThatFit.map(({ el }) => el) return { fit: elsThatFit, notFit: getCacheFor(nav.__id).children.filter((el) => { return !elsThatFit.includes(el) }), } }