/* Place a sticky menu at the top of your page - has both icons and text, the way it should be */ function IconMenu(options) { this.layout = options.layout; //Menu items - https://css-tricks.com/using-flexbox/ var menuCSS = this.layout.setCSSFromSelector(".menuRow", { position: "relative", display: "-webkit-box", alignItems: "stretch", flexDirection: "row", justifyContent: "center" }) //use alignItems flex-end, if you want them to align bottom instead of getting equal height. menuCSS.style.display = "-moz-box"; menuCSS.style.display = "-ms-flexbox"; menuCSS.style.display = "-webkit-flex"; menuCSS.style.display = "flex"; var mainColor = (options.style && options.style.color) || "white" var backgroundColor = (options.style && options.style.backgroundColor) || "blue" var borderStyle = "solid 1px " + mainColor; var menuContainer = this.layout.setCSSFromSelector(".menuContainer", { borderBottom: borderStyle, backgroundColor: backgroundColor, top: "0px", zIndex: 20, position: "sticky" }) menuContainer.style.position = "-webkit-sticky" this.layout.applyCSS({ ".menuItem": { flexGrow: 1, flexBasis: "10px", borderRight: borderStyle, padding: "5px", maxWidth: "100px" }, ".menuItem:last-child": { borderRight: "none" }, ".menuItemText": { textDecoration: "inherit", textAlign: "center", fontSize: "small", color: "white" }, ".menuItemImg": { display: "block", width: "44px", height: "44px", margin: "auto" }, ".menuImageParent": { position : "relative", }, //perspective: "14px" ".menuSelected": { textDecoration: "underline", textTransform: "uppercase", }, //textShadow: "-1px -1px 0 #000, 1px -1px 0 #000,-1px 1px 0 #000, 1px 1px 0 #000" ".menuItem:hover": { textDecoration: "underline", textTransform: "uppercase", }, }) } IconMenu.prototype = { templateJSON: function() { return this.menuJSON || {}; }, setContentData: function(items) { //TODO: change this to make use of flexBox handling of rows instead. At the moment this is pointless. //No wait - if they cannot fit, turn the last button to a hamburger menu - and if clicked expands to a callout-menu (regular). var minWidth = 64; //44 + 5 + 5 - change this to use margins var divWidth = 320; //this.layout.elements.rootElement.offsetWidth; var maxItemsPerRow = Math.floor( divWidth / minWidth ) var totalRows = Math.ceil(items.length / maxItemsPerRow ) var itemsPerRow = Math.ceil( items.length / totalRows ) //we need to even-out the empty spaces if there are more than one //NO! We don't need to do this anymore, we can let flexBox handle that. var lastRowEmptySpaces = itemsPerRow * totalRows - items.length; //but how far before the end? var subRowBegin = totalRows - lastRowEmptySpaces; var rowChildren = [] var menuChildren = [] for (var index = 0; index < items.length; index++) { var item = items[index] var textDiv = item.text; if (textDiv) { if (textDiv.className) textDiv.className = "menuItemText " + textDiv.className; else textDiv.className = "menuItemText" } var imageDiv = item.image; if (imageDiv) { imageDiv.autoType = AUTO_TYPE.image if (imageDiv.className) imageDiv.className += " menuItemImg"; else imageDiv.className = "menuItemImg" } var link = item.link; link.autoType = AUTO_TYPE.anchorLink if (link.className) link.className += " menuItem" else link.className = "menuItem" link.children = [{ className: "menuImageParent", children : [imageDiv] }, textDiv] rowChildren.push(link); var extraOverflow = false; if (lastRowEmptySpaces > 1 && subRowBegin == menuChildren.length && rowChildren.length == itemsPerRow - 1) { //if we are not on the first row, and have more than one space left on the last row - we take one item from the other rows and put it last extraOverflow = true; lastRowEmptySpaces--; subRowBegin++; } if (extraOverflow || rowChildren.length == itemsPerRow) { menuChildren.push({ className : "menuRow", children : rowChildren }) rowChildren = [] } } if (rowChildren.length) menuChildren.push({ className : "menuRow", children : rowChildren }) this.menuJSON = { className: "menuContainer", children: [ { className : "menu", children: menuChildren } ]} }, //We use the fact that the link is an anchorLink that has key=value for what we are looking for markSelected: function(itemTitle) { if (this.selectedTitle == itemTitle || !this.menuJSON) return; //deep copy so we can compare with previous JSON: this.menuJSON = JSON.parse(JSON.stringify(this.menuJSON)) var selectedClass = "menuSelected" var rowChildren = this.menuJSON.children[0].children[0].children; //find the current one and mark that for (var index = 0; index < rowChildren.length; index++) { var link = rowChildren[index]; //unmark the previous item if (this.previousSelection && link.value == this.previousSelection) { var className = link.className; var position = className.indexOf(selectedClass) if (position !== -1) { link.className = className.substring(0, position - 1) } } if (link.value == itemTitle) { link.className += " " + selectedClass } } this.previousSelection = itemTitle; } }