Created
August 8, 2015 16:04
-
-
Save Noble-Mushtak/900ae6825bbc0f9f0f4a to your computer and use it in GitHub Desktop.
Lightweight Dropdowns:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//The event names. These change according to whether or not the user is on a mobile device, or specifically a Windows Phone. | |
var isIEMobile = navigator.userAgent.indexOf("IEMobile") != -1; | |
var isMobile = navigator.userAgent.indexOf("Mobile") != -1; | |
var mouseevents = { | |
click: "click", | |
mousedown: isIEMobile ? "pointerdown" : (isMobile ? "touchstart" : "mousedown"), | |
mouseup: isIEMobile ? "pointerup" : (isMobile ? "touchend" : "mouseup"), | |
mousemove: isIEMobile ? "pointermove" : (isMobile ? "touchmove" : "mousemove"), | |
mouseenter: isIEMobile ? "pointerenter" : (isMobile ? "touchenter" : "mouseenter"), | |
mouseleave: isIEMobile ? "pointerleave" : (isMobile ? "touchleave" : "mouseleave") | |
}; | |
//The different dropdown bars for the different tabs. | |
var dropdowns = [ | |
/*blog:*/ [document.createElement("a"), document.createElement("a")], | |
/*writings:*/ [document.createElement("span")], | |
/*code:*/ [document.createElement("a"), document.createElement("a"), document.createElement("a")], | |
/*otherStuff:*/ [document.createElement("a"), document.createElement("a")] | |
]; | |
//Here, we set the link, title, and text content of each dropdown. | |
dropdowns[0][0].href = "/blog/"; | |
dropdowns[0][0].title = "A list of all of the blog posts"; | |
dropdowns[0][0].textContent = "Blog Home"; | |
dropdowns[0][1].href = "/blog/rss-feed.rss"; | |
dropdowns[0][1].title = "An RSS Feed to help you keep up with blog posts"; | |
dropdowns[0][1].textContent = "RSS Feed"; | |
dropdowns[1][0].textContent = "Nothing Yet!"; | |
dropdowns[1][0].title = "Will come eventually!" | |
dropdowns[2][0].href = "/Code%20Base"; | |
dropdowns[2][0].title = "A place where I keep all of my code"; | |
dropdowns[2][0].textContent = "Code Base"; | |
dropdowns[2][1].href = "/Projects"; | |
dropdowns[2][1].title = "A bunch of projects hosted on this site."; | |
dropdowns[2][1].textContent = "Projects"; | |
dropdowns[2][2].href = "/HTML%20Lessons"; | |
dropdowns[2][2].title = "Learn HTML and CSS from this website!"; | |
dropdowns[2][2].textContent = "HTML Lessons"; | |
dropdowns[3][0].href = "/Chat%20Center"; | |
dropdowns[3][0].title = "A place where you can chat with everyone else on the site!"; | |
dropdowns[3][0].textContent = "Chat Center"; | |
dropdowns[3][1].href = "/Online%20Stuff"; | |
dropdowns[3][1].title = "The random things I do while on the Internet"; | |
dropdowns[3][1].textContent = "Online Stuff"; | |
//All of the tabs in the heading. | |
var tabs = document.querySelectorAll("#tabs > *"); | |
//The parent node of the tabs. | |
var container = tabs[0].parentNode; | |
//An invisible element with an absolute position that we copy for each dropdown. | |
var absoluteDiv = document.createElement("div"); | |
absoluteDiv.className = "col-md-2 col-xs-2"; | |
absoluteDiv.style.position = "absolute"; | |
absoluteDiv.style.display = "none"; | |
absoluteDiv.style.opacity = 1; | |
//Counters that store the return of a setTimeout() function to be passed into clearTimeout() if necessary. | |
var counters = [ | |
/*blog:*/ null, | |
/*writings:*/ null, | |
/*code:*/ null, | |
/*otherStuff:*/ null | |
]; | |
//An event function generator that shows a bunch of absolutely position divs such that they look like a dropdown bar. | |
var dropdownShowEvent = function(index) { | |
return function() { | |
if (counters[index] != null) { | |
clearTimeout(counters[index]); | |
counters[index] = null; | |
} | |
for (var i = 0; i < dropdowns[index].length; i++) dropdowns[index][i].style.display = "block"; | |
}; | |
}; | |
//A utility function for dropdownHideEvent that hides a dropdown bar. | |
var hideDropdowns = function(index) { | |
var elems = dropdowns[index]; | |
counters[index] = null; | |
for (var i = 0; i < elems.length; i++) elems[i].style.display = "none"; | |
}; | |
//An event function generator that fades out and hides dropdown bars if the mouse isn't over them. | |
var dropdownHideEvent = function(index) { | |
return function eventHandler() { | |
if (counters[index]) { | |
hideDropdowns(index); | |
} else { | |
counters[index] = setTimeout(eventHandler, 200); | |
} | |
}; | |
}; | |
//This initalized the dropdown bars by creating them and giving both the tabs and them event handlers. | |
for (var i = 0; i < dropdowns.length; i++) { | |
var eventShowHandler = dropdownShowEvent(i); | |
var eventHideHandler = dropdownHideEvent(i); | |
//Only need to initiate capture on mobile devices | |
tabs[i].addEventListener(isMobile ? mouseevents.mousedown : mouseevents.mouseenter, eventShowHandler, isMobile); | |
//On mobile devices, we want the dropdown menus to dispear when we click somewhere else. Otherwise, we just hide it when the mouse has left the dropdown bar. | |
if (isMobile) document.body.addEventListener(mouseevents.mousedown, eventHideHandler, true); | |
else tabs[i].addEventListener(mouseevents.mouseleave, eventHideHandler); | |
for (var j = 0; j < dropdowns[i].length; j++) { | |
var dropdown = absoluteDiv.cloneNode(); | |
dropdown.appendChild(dropdowns[i][j]); | |
dropdowns[i][j] = dropdown; | |
dropdown.addEventListener(isMobile ? mouseevents.mousedown : mouseevents.mouseenter, eventShowHandler); | |
if (!isMobile) dropdown.addEventListener(mouseevents.mouseleave, eventHideHandler); | |
container.insertBefore(dropdown, container.firstChild); | |
} | |
} | |
var positionDropdowns = function() { | |
/*This positions the dropdown bars.*/ | |
for (var i = 0; i < dropdowns.length; i++) { | |
var locationStats = tabs[i].getBoundingClientRect(); | |
var prevLocStats = { | |
top: locationStats.top+window.pageYOffset, | |
height: locationStats.height, | |
left: locationStats.left+window.pageXOffset-0.04*document.body.clientWidth | |
}; | |
for (var j = 0; j < dropdowns[i].length; j++) { | |
var dropdown = dropdowns[i][j]; | |
dropdown.style.left = prevLocStats.left+"px"; | |
dropdown.style.top = prevLocStats.top+prevLocStats.height+"px"; | |
prevLocStats.top += prevLocStats.height; | |
dropdown.style.display = "block"; | |
prevLocStats.height = dropdown.clientHeight; | |
dropdown.style.display = "none"; | |
} | |
} | |
}; | |
//We position the dropdowns in the beginning of the page load and when the window is resized. | |
positionDropdowns(); | |
window.addEventListener("resize", positionDropdowns); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment