├── README.md ├── css ├── component.css └── default.css ├── fonts ├── bpicons │ ├── bpicons.eot │ ├── bpicons.svg │ ├── bpicons.ttf │ ├── bpicons.woff │ └── license.txt └── tmicons │ ├── cbp-tmicons.dev.svg │ ├── cbp-tmicons.eot │ ├── cbp-tmicons.svg │ ├── cbp-tmicons.ttf │ ├── cbp-tmicons.woff │ └── license.txt ├── index.html └── js ├── cbpTooltipMenu.js ├── cbpTooltipMenu.min.js └── modernizr.custom.js /README.md: -------------------------------------------------------------------------------- 1 | 2 | Tooltip Menu 3 | ========= 4 | 5 | This is a simple tooltip menu that will show a tooltip submenu when hovering over an item. The submenu will either appear above or below the main menu, depending on where more space is available. Using Modernizr's touch detection, the menu will either react on hover or on click. Example media queries show how to adjust the style for smaller screens. 6 | 7 | [article on Codrops](http://tympanus.net/codrops/?p=15212) 8 | 9 | [demo](http://tympanus.net/Blueprints/TooltipMenu/) 10 | 11 | [LICENSING & TERMS OF USE](http://tympanus.net/codrops/licensing/) -------------------------------------------------------------------------------- /css/component.css: -------------------------------------------------------------------------------- 1 | /* Iconfont made with icomoon.com */ 2 | @font-face { 3 | font-family: 'cbp-tmicons'; 4 | src:url('../fonts/tmicons/cbp-tmicons.eot'); 5 | src:url('../fonts/tmicons/cbp-tmicons.eot?#iefix') format('embedded-opentype'), 6 | url('../fonts/tmicons/cbp-tmicons.woff') format('woff'), 7 | url('../fonts/tmicons/cbp-tmicons.ttf') format('truetype'), 8 | url('../fonts/tmicons/cbp-tmicons.svg#cbp-tmicons') format('svg'); 9 | font-weight: normal; 10 | font-style: normal; 11 | } 12 | 13 | /* reset list style */ 14 | .cbp-tm-menu, 15 | .cbp-tm-menu ul { 16 | list-style: none; 17 | } 18 | 19 | /* set menu position; change here to set to relative or float, etc. */ 20 | .cbp-tm-menu { 21 | display: block; 22 | position: absolute; 23 | z-index: 1000; 24 | bottom: 0; 25 | width: 100%; 26 | background: #47a3da; 27 | text-align: right; 28 | padding: 0 2em; 29 | margin: 0; 30 | text-transform: capitalize; 31 | } 32 | 33 | /* first level menu items */ 34 | .cbp-tm-menu > li { 35 | display: inline-block; 36 | margin: 0 2.6em; 37 | position: relative; 38 | } 39 | 40 | .cbp-tm-menu > li > a { 41 | line-height: 4em; 42 | padding: 0 0.3em; 43 | font-size: 1.2em; 44 | display: block; 45 | color: #fff; 46 | } 47 | 48 | .no-touch .cbp-tm-menu > li > a:hover, 49 | .no-touch .cbp-tm-menu > li > a:active { 50 | color: #02639d; 51 | } 52 | 53 | /* sumbenu with transitions */ 54 | .cbp-tm-submenu { 55 | position: absolute; 56 | display: block; 57 | visibility: hidden; 58 | opacity: 0; 59 | padding: 0; 60 | text-align: left; 61 | pointer-events: none; 62 | -webkit-transition: visibility 0s, opacity 0s; 63 | -moz-transition: visibility 0s, opacity 0s; 64 | transition: visibility 0s, opacity 0s; 65 | } 66 | 67 | .cbp-tm-show .cbp-tm-submenu { 68 | width: 16em; 69 | left: 50%; 70 | margin: 0 0 0 -8em; 71 | opacity: 1; 72 | visibility: visible; 73 | pointer-events: auto; 74 | -webkit-transition: visibility 0s, opacity 0.3s; 75 | -moz-transition: visibility 0s, opacity 0.3s; 76 | transition: visibility 0s, opacity 0.3s; 77 | } 78 | 79 | .cbp-tm-show-above .cbp-tm-submenu { 80 | bottom: 100%; 81 | padding-bottom: 10px; 82 | } 83 | 84 | .cbp-tm-show-below .cbp-tm-submenu { 85 | top: 100%; 86 | padding-top: 10px; 87 | } 88 | 89 | /* extreme cases: not enough space on the sides */ 90 | .cbp-tm-nospace-right .cbp-tm-submenu { 91 | right: 0; 92 | left: auto; 93 | } 94 | 95 | .cbp-tm-nospace-left .cbp-tm-submenu { 96 | left: 0; 97 | } 98 | 99 | /* last menu item has to fit on the screen */ 100 | .cbp-tm-menu > li:last-child .cbp-tm-submenu { 101 | right: 0; 102 | } 103 | 104 | /* 105 | arrow: depending on where the menu will be shown, we set 106 | the right position for the arrow 107 | */ 108 | 109 | .cbp-tm-submenu:after { 110 | border: solid transparent; 111 | content: " "; 112 | height: 0; 113 | width: 0; 114 | position: absolute; 115 | pointer-events: none; 116 | } 117 | 118 | .cbp-tm-show-above .cbp-tm-submenu:after { 119 | top: 100%; 120 | margin-top: -10px; 121 | } 122 | 123 | .cbp-tm-show-below .cbp-tm-submenu:after { 124 | bottom: 100%; 125 | margin-bottom: -10px; 126 | } 127 | 128 | .cbp-tm-submenu:after { 129 | border-color: transparent; 130 | border-width: 16px; 131 | margin-left: -16px; 132 | left: 50%; 133 | } 134 | 135 | .cbp-tm-show-above .cbp-tm-submenu:after { 136 | border-top-color: #fff; 137 | } 138 | 139 | .cbp-tm-show-below .cbp-tm-submenu:after { 140 | border-bottom-color: #fff; 141 | } 142 | 143 | .cbp-tm-submenu > li { 144 | display: block; 145 | background: #fff; 146 | } 147 | 148 | .cbp-tm-submenu > li > a { 149 | padding: 5px 2.3em 5px 0.6em; /* top/bottom paddings in 'em' cause a tiny "jump" in Chrome on Win */ 150 | display: block; 151 | font-size: 1.2em; 152 | position: relative; 153 | color: #47a3da; 154 | border: 4px solid #fff; 155 | -webkit-transition: all 0.2s; 156 | -moz-transition: all 0.2s; 157 | transition: all 0.2s; 158 | } 159 | 160 | .no-touch .cbp-tm-submenu > li > a:hover, 161 | .no-touch .cbp-tm-submenu > li > a:active { 162 | color: #fff; 163 | background: #47a3da; 164 | } 165 | 166 | /* the icons (main level menu icon and sublevel icons) */ 167 | .cbp-tm-submenu li a:before, 168 | .cbp-tm-menu > li > a:before { 169 | font-family: 'cbp-tmicons'; 170 | speak: none; 171 | font-style: normal; 172 | font-weight: normal; 173 | font-variant: normal; 174 | text-transform: none; 175 | line-height: 1; 176 | vertical-align: middle; 177 | margin-right: 0.6em; 178 | -webkit-font-smoothing: antialiased; 179 | } 180 | 181 | .cbp-tm-submenu li a:before { 182 | position: absolute; 183 | top: 50%; 184 | margin-top: -0.5em; 185 | right: 0.5em; 186 | } 187 | 188 | .cbp-tm-menu > li > a:not(:only-child):before { 189 | content: "\f0c9"; 190 | font-size: 60%; 191 | opacity: 0.3; 192 | } 193 | 194 | .cbp-tm-icon-archive:before { 195 | content: "\e002"; 196 | } 197 | 198 | .cbp-tm-icon-cog:before { 199 | content: "\e003"; 200 | } 201 | 202 | .cbp-tm-icon-users:before { 203 | content: "\e004"; 204 | } 205 | 206 | .cbp-tm-icon-earth:before { 207 | content: "\e005"; 208 | } 209 | 210 | .cbp-tm-icon-location:before { 211 | content: "\e006"; 212 | } 213 | 214 | .cbp-tm-icon-mobile:before { 215 | content: "\e007"; 216 | } 217 | 218 | .cbp-tm-icon-screen:before { 219 | content: "\e008"; 220 | } 221 | 222 | .cbp-tm-icon-mail:before { 223 | content: "\e009"; 224 | } 225 | 226 | .cbp-tm-icon-contract:before { 227 | content: "\e00a"; 228 | } 229 | 230 | .cbp-tm-icon-pencil:before { 231 | content: "\e00b"; 232 | } 233 | 234 | .cbp-tm-icon-article:before { 235 | content: "\e00c"; 236 | } 237 | 238 | .cbp-tm-icon-clock:before { 239 | content: "\e00d"; 240 | } 241 | 242 | .cbp-tm-icon-videos:before { 243 | content: "\e00e"; 244 | } 245 | 246 | .cbp-tm-icon-pictures:before { 247 | content: "\e00f"; 248 | } 249 | 250 | .cbp-tm-icon-link:before { 251 | content: "\e010"; 252 | } 253 | 254 | .cbp-tm-icon-refresh:before { 255 | content: "\e011"; 256 | } 257 | 258 | .cbp-tm-icon-help:before { 259 | content: "\e012"; 260 | } 261 | 262 | /* Media Queries */ 263 | @media screen and (max-width: 55.6875em) { 264 | .cbp-tm-menu { 265 | font-size: 80%; 266 | } 267 | } 268 | 269 | @media screen and (max-height: 25.25em), screen and (max-width: 44.3125em) { 270 | 271 | .cbp-tm-menu { 272 | font-size: 100%; 273 | position: relative; 274 | text-align: center; 275 | padding: 0; 276 | top: auto; 277 | } 278 | 279 | .cbp-tm-menu > li { 280 | display: block; 281 | margin: 0; 282 | border-bottom: 4px solid #3793ca; 283 | } 284 | 285 | .cbp-tm-menu > li:first-child { 286 | border-top: 4px solid #3793ca; 287 | } 288 | 289 | li.cbp-tm-show > a, 290 | .no-touch .cbp-tm-menu > li > a:hover, 291 | .no-touch .cbp-tm-menu > li > a:active { 292 | color: #fff; 293 | background: #02639d; 294 | } 295 | 296 | .cbp-tm-submenu { 297 | position: relative; 298 | display: none; 299 | width: 100%; 300 | } 301 | 302 | .cbp-tm-submenu > li { 303 | padding: 0; 304 | } 305 | 306 | .cbp-tm-submenu > li > a { 307 | padding: 0.6em 2.3em 0.6em 0.6em; 308 | border: none; 309 | border-bottom: 2px solid #6fbbe9; 310 | } 311 | 312 | .cbp-tm-submenu:after { 313 | display: none; 314 | } 315 | 316 | .cbp-tm-menu .cbp-tm-show .cbp-tm-submenu { 317 | display: block; 318 | width: 100%; 319 | left: 0; 320 | margin: 0; 321 | padding: 0; 322 | } 323 | 324 | } 325 | -------------------------------------------------------------------------------- /css/default.css: -------------------------------------------------------------------------------- 1 | /* General Blueprint Style */ 2 | @import url(http://fonts.googleapis.com/css?family=Lato:300,400,700); 3 | @font-face { 4 | font-family: 'bpicons'; 5 | src:url('../fonts/bpicons/bpicons.eot'); 6 | src:url('../fonts/bpicons/bpicons.eot?#iefix') format('embedded-opentype'), 7 | url('../fonts/bpicons/bpicons.woff') format('woff'), 8 | url('../fonts/bpicons/bpicons.ttf') format('truetype'), 9 | url('../fonts/bpicons/bpicons.svg#bpicons') format('svg'); 10 | font-weight: normal; 11 | font-style: normal; 12 | } /* Made with http://icomoon.io/ */ 13 | 14 | *, *:after, *:before { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } 15 | body, html { font-size: 100%; padding: 0; margin: 0; height: 100%;} 16 | 17 | /* Clearfix hack by Nicolas Gallagher: http://nicolasgallagher.com/micro-clearfix-hack/ */ 18 | .clearfix:before, .clearfix:after { content: " "; display: table; } 19 | .clearfix:after { clear: both; } 20 | 21 | body { 22 | font-family: 'Lato', Calibri, Arial, sans-serif; 23 | color: #47a3da; 24 | } 25 | 26 | a { 27 | color: #f0f0f0; 28 | outline: none; 29 | text-decoration: none; 30 | } 31 | 32 | a:hover { 33 | color: #000; 34 | } 35 | 36 | .container > header { 37 | width: 90%; 38 | max-width: 69em; 39 | margin: 0 auto; 40 | z-index: 1000; 41 | position: relative; 42 | padding: 2.875em 1.875em 1.875em; 43 | } 44 | 45 | .container { 46 | height: 100%; 47 | position: relative; 48 | } 49 | 50 | .filler-above, 51 | .filler-below { 52 | width: 100%; 53 | height: 100%; 54 | position: absolute; 55 | background: #f0f0f0; 56 | } 57 | 58 | .filler-above p { 59 | max-width: 40em; 60 | margin: 0 auto; 61 | text-align: center; 62 | padding: 3em 2em; 63 | } 64 | 65 | .filler-below { 66 | top: 100%; 67 | background: #85caf4; 68 | } 69 | 70 | .container > header h1 { 71 | font-size: 2.125em; 72 | line-height: 1.3; 73 | margin: 0 0 0.6em 0; 74 | float: left; 75 | font-weight: 400; 76 | } 77 | 78 | .container > header > span { 79 | display: block; 80 | position: relative; 81 | z-index: 9999; 82 | font-weight: 700; 83 | text-transform: uppercase; 84 | letter-spacing: 0.5em; 85 | padding: 0 0 0.6em 0.1em; 86 | } 87 | 88 | .container > header > span span:after { 89 | width: 30px; 90 | height: 30px; 91 | left: -12px; 92 | font-size: 50%; 93 | top: -8px; 94 | font-size: 75%; 95 | position: relative; 96 | } 97 | 98 | .container > header > span span:hover:before { 99 | content: attr(data-content); 100 | text-transform: none; 101 | text-indent: 0; 102 | letter-spacing: 0; 103 | font-weight: 300; 104 | font-size: 110%; 105 | padding: 0.8em 1em; 106 | line-height: 1.2; 107 | text-align: left; 108 | left: auto; 109 | margin-left: 4px; 110 | position: absolute; 111 | color: #fff; 112 | background: #47a3da; 113 | } 114 | 115 | .container > header nav { 116 | float: right; 117 | text-align: center; 118 | } 119 | 120 | .container > header nav a { 121 | display: inline-block; 122 | position: relative; 123 | text-align: left; 124 | width: 2.5em; 125 | height: 2.5em; 126 | background: #fff; 127 | border-radius: 50%; 128 | margin: 0 0.1em; 129 | border: 4px solid #47a3da; 130 | } 131 | 132 | .container > header nav a > span { 133 | display: none; 134 | } 135 | 136 | .container > header nav a:hover:before { 137 | content: attr(data-info); 138 | color: #47a3da; 139 | position: absolute; 140 | width: 600%; 141 | top: 120%; 142 | text-align: right; 143 | right: 0; 144 | pointer-events: none; 145 | } 146 | 147 | .container > header nav a:hover { 148 | background: #47a3da; 149 | } 150 | 151 | .bp-icon:after { 152 | font-family: 'bpicons'; 153 | speak: none; 154 | font-style: normal; 155 | font-weight: normal; 156 | font-variant: normal; 157 | text-transform: none; 158 | text-align: center; 159 | color: #47a3da; 160 | -webkit-font-smoothing: antialiased; 161 | } 162 | 163 | .container > header nav .bp-icon:after { 164 | position: absolute; 165 | top: 0; 166 | left: 0; 167 | width: 100%; 168 | height: 100%; 169 | line-height: 2; 170 | text-indent: 0; 171 | } 172 | 173 | .container > header nav a:hover:after { 174 | color: #fff; 175 | } 176 | 177 | .bp-icon-next:after { 178 | content: "\e000"; 179 | } 180 | 181 | .bp-icon-drop:after { 182 | content: "\e001"; 183 | } 184 | 185 | .bp-icon-archive:after { 186 | content: "\e002"; 187 | } 188 | 189 | .bp-icon-about:after { 190 | content: "\e003"; 191 | } 192 | 193 | .bp-icon-prev:after { 194 | content: "\e004"; 195 | } 196 | 197 | @media screen and (max-width: 55em) { 198 | 199 | .container > header h1, 200 | .container > header nav { 201 | float: none; 202 | } 203 | 204 | .container > header > span, 205 | .container > header h1 { 206 | text-align: center; 207 | } 208 | 209 | .container > header nav { 210 | margin: 0 auto; 211 | } 212 | 213 | .container > header > span { 214 | text-indent: 30px; 215 | } 216 | } 217 | 218 | @media screen and (max-height: 25.25em), screen and (max-width: 44.3125em) { 219 | 220 | .filler-above, 221 | .filler-below { 222 | position: relative; 223 | background: #f0f0f0; 224 | height: auto; 225 | } 226 | 227 | } 228 | -------------------------------------------------------------------------------- /fonts/bpicons/bpicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/TooltipMenu/c3f3bb4bcc9b0079d542d13fab7b64789f282b24/fonts/bpicons/bpicons.eot -------------------------------------------------------------------------------- /fonts/bpicons/bpicons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This is a custom SVG font generated by IcoMoon. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /fonts/bpicons/bpicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/TooltipMenu/c3f3bb4bcc9b0079d542d13fab7b64789f282b24/fonts/bpicons/bpicons.ttf -------------------------------------------------------------------------------- /fonts/bpicons/bpicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/TooltipMenu/c3f3bb4bcc9b0079d542d13fab7b64789f282b24/fonts/bpicons/bpicons.woff -------------------------------------------------------------------------------- /fonts/bpicons/license.txt: -------------------------------------------------------------------------------- 1 | Icon Set: Font Awesome -- http://fortawesome.github.com/Font-Awesome/ 2 | License: SIL -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL 3 | 4 | 5 | Icon Set: Eco Ico -- http://dribbble.com/shots/665585-Eco-Ico 6 | License: CC0 -- http://creativecommons.org/publicdomain/zero/1.0/ -------------------------------------------------------------------------------- /fonts/tmicons/cbp-tmicons.dev.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This is a custom SVG font generated by IcoMoon. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 25 | 26 | 34 | 43 | 52 | 54 | 57 | 60 | 65 | 68 | 71 | 75 | 79 | 82 | 90 | 94 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /fonts/tmicons/cbp-tmicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/TooltipMenu/c3f3bb4bcc9b0079d542d13fab7b64789f282b24/fonts/tmicons/cbp-tmicons.eot -------------------------------------------------------------------------------- /fonts/tmicons/cbp-tmicons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | This is a custom SVG font generated by IcoMoon. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 25 | 26 | 34 | 43 | 52 | 54 | 57 | 60 | 65 | 68 | 71 | 75 | 79 | 82 | 90 | 94 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /fonts/tmicons/cbp-tmicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/TooltipMenu/c3f3bb4bcc9b0079d542d13fab7b64789f282b24/fonts/tmicons/cbp-tmicons.ttf -------------------------------------------------------------------------------- /fonts/tmicons/cbp-tmicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/TooltipMenu/c3f3bb4bcc9b0079d542d13fab7b64789f282b24/fonts/tmicons/cbp-tmicons.woff -------------------------------------------------------------------------------- /fonts/tmicons/license.txt: -------------------------------------------------------------------------------- 1 | Icon Set: Font Awesome -- http://fortawesome.github.com/Font-Awesome/ 2 | License: SIL -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL 3 | 4 | 5 | Icon Set: Eco Ico -- http://dribbble.com/shots/665585-Eco-Ico 6 | License: CC0 -- http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | 9 | Icon Set: IcoMoon - Free -- http://keyamoon.com/icomoon/ 10 | License: CC BY 3.0 -- http://creativecommons.org/licenses/by/3.0/ -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Blueprint: Tooltip Menu 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 | Blueprint 20 |

Tooltip Menu

21 | 27 |
28 |
29 |

The tooltip submenu will appear either above or below the menu, depending on where more space is available. Scroll down to see it appearing below.

30 |
31 | 71 |
72 |
73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /js/cbpTooltipMenu.js: -------------------------------------------------------------------------------- 1 | /** 2 | * cbpTooltipMenu.js v1.0.0 3 | * http://www.codrops.com 4 | * 5 | * Licensed under the MIT license. 6 | * http://www.opensource.org/licenses/mit-license.php 7 | * 8 | * Copyright 2013, Codrops 9 | * http://www.codrops.com 10 | */ 11 | ;( function( window ) { 12 | 13 | 'use strict'; 14 | 15 | var document = window.document, 16 | docElem = document.documentElement; 17 | 18 | function extend( a, b ) { 19 | for( var key in b ) { 20 | if( b.hasOwnProperty( key ) ) { 21 | a[key] = b[key]; 22 | } 23 | } 24 | return a; 25 | } 26 | 27 | // from https://github.com/ryanve/response.js/blob/master/response.js 28 | function getViewportH() { 29 | var client = docElem['clientHeight'], 30 | inner = window['innerHeight']; 31 | if( client < inner ) 32 | return inner; 33 | else 34 | return client; 35 | } 36 | 37 | // http://stackoverflow.com/a/11396681/989439 38 | function getOffset( el ) { 39 | return el.getBoundingClientRect(); 40 | } 41 | 42 | // http://snipplr.com/view.php?codeview&id=5259 43 | function isMouseLeaveOrEnter(e, handler) { 44 | if (e.type != 'mouseout' && e.type != 'mouseover') return false; 45 | var reltg = e.relatedTarget ? e.relatedTarget : 46 | e.type == 'mouseout' ? e.toElement : e.fromElement; 47 | while (reltg && reltg != handler) reltg = reltg.parentNode; 48 | return (reltg != handler); 49 | } 50 | 51 | function cbpTooltipMenu( el, options ) { 52 | this.el = el; 53 | this.options = extend( this.defaults, options ); 54 | this._init(); 55 | } 56 | 57 | cbpTooltipMenu.prototype = { 58 | defaults : { 59 | // add a timeout to avoid the menu to open instantly 60 | delayMenu : 100 61 | }, 62 | _init : function() { 63 | this.touch = Modernizr.touch; 64 | this.menuItems = document.querySelectorAll( '#' + this.el.id + ' > li' ); 65 | this._initEvents(); 66 | }, 67 | _initEvents : function() { 68 | 69 | var self = this; 70 | 71 | Array.prototype.slice.call( this.menuItems ).forEach( function( el, i ) { 72 | var trigger = el.querySelector( 'a' ); 73 | if( self.touch ) { 74 | trigger.addEventListener( 'click', function( ev ) { self._handleClick( this, ev ); } ); 75 | } 76 | else { 77 | trigger.addEventListener( 'click', function( ev ) { 78 | if( this.parentNode.querySelector( 'ul.cbp-tm-submenu' ) ) { 79 | ev.preventDefault(); 80 | } 81 | } ); 82 | el.addEventListener( 'mouseover', function(ev) { if( isMouseLeaveOrEnter( ev, this ) ) self._openMenu( this ); } ); 83 | el.addEventListener( 'mouseout', function(ev) { if( isMouseLeaveOrEnter( ev, this ) ) self._closeMenu( this ); } ); 84 | } 85 | } ); 86 | 87 | }, 88 | _openMenu : function( el ) { 89 | 90 | var self = this; 91 | clearTimeout( this.omtimeout ); 92 | this.omtimeout = setTimeout( function() { 93 | var submenu = el.querySelector( 'ul.cbp-tm-submenu' ); 94 | 95 | if( submenu ) { 96 | el.className = 'cbp-tm-show'; 97 | if( self._positionMenu( el ) === 'top' ) { 98 | el.className += ' cbp-tm-show-above'; 99 | } 100 | else { 101 | el.className += ' cbp-tm-show-below'; 102 | } 103 | } 104 | }, this.touch ? 0 : this.options.delayMenu ); 105 | 106 | }, 107 | _closeMenu : function( el ) { 108 | 109 | clearTimeout( this.omtimeout ); 110 | 111 | var submenu = el.querySelector( 'ul.cbp-tm-submenu' ); 112 | 113 | if( submenu ) { 114 | // based on https://github.com/desandro/classie/blob/master/classie.js 115 | el.className = el.className.replace(new RegExp("(^|\\s+)" + "cbp-tm-show" + "(\\s+|$)"), ' '); 116 | el.className = el.className.replace(new RegExp("(^|\\s+)" + "cbp-tm-show-below" + "(\\s+|$)"), ' '); 117 | el.className = el.className.replace(new RegExp("(^|\\s+)" + "cbp-tm-show-above" + "(\\s+|$)"), ' '); 118 | } 119 | 120 | }, 121 | _handleClick : function( el, ev ) { 122 | var item = el.parentNode, 123 | items = Array.prototype.slice.call( this.menuItems ), 124 | submenu = item.querySelector( 'ul.cbp-tm-submenu' ) 125 | 126 | // first close any opened one.. 127 | if( typeof this.current !== 'undefined' && items.indexOf( item ) !== this.current ) { 128 | this._closeMenu( this.el.children[ this.current ] ); 129 | this.el.children[ this.current ].querySelector( 'ul.cbp-tm-submenu' ).setAttribute( 'data-open', 'false' ); 130 | } 131 | 132 | if( submenu ) { 133 | ev.preventDefault(); 134 | 135 | var isOpen = submenu.getAttribute( 'data-open' ); 136 | 137 | if( isOpen === 'true' ) { 138 | this._closeMenu( item ); 139 | submenu.setAttribute( 'data-open', 'false' ); 140 | } 141 | else { 142 | this._openMenu( item ); 143 | this.current = items.indexOf( item ); 144 | submenu.setAttribute( 'data-open', 'true' ); 145 | } 146 | } 147 | 148 | }, 149 | _positionMenu : function( el ) { 150 | // checking where's more space left in the viewport: above or below the element 151 | var vH = getViewportH(), 152 | ot = getOffset(el), 153 | spaceUp = ot.top , 154 | spaceDown = vH - spaceUp - el.offsetHeight; 155 | 156 | return ( spaceDown <= spaceUp ? 'top' : 'bottom' ); 157 | } 158 | } 159 | 160 | // add to global namespace 161 | window.cbpTooltipMenu = cbpTooltipMenu; 162 | 163 | } )( window ); -------------------------------------------------------------------------------- /js/cbpTooltipMenu.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * cbpTooltipMenu.min.js v1.0.0 3 | * http://www.codrops.com 4 | * 5 | * Licensed under the MIT license. 6 | * http://www.opensource.org/licenses/mit-license.php 7 | * 8 | * Copyright 2013, Codrops 9 | * http://www.codrops.com 10 | */ 11 | (function(d){var c=d.document,b=c.documentElement;function h(j,i){for(var k in i){if(i.hasOwnProperty(k)){j[k]=i[k]}}return j}function a(){var i=b.clientHeight,j=d.innerHeight;if(i li");this._initEvents()},_initEvents:function(){var i=this;Array.prototype.slice.call(this.menuItems).forEach(function(l,k){var j=l.querySelector("a");if(i.touch){j.addEventListener("click",function(m){i._handleClick(this,m)})}else{j.addEventListener("click",function(m){if(this.parentNode.querySelector("ul.cbp-tm-submenu")){m.preventDefault()}});l.addEventListener("mouseover",function(m){if(e(m,this)){i._openMenu(this)}});l.addEventListener("mouseout",function(m){if(e(m,this)){i._closeMenu(this)}})}})},_openMenu:function(j){var i=this;clearTimeout(this.omtimeout);this.omtimeout=setTimeout(function(){var k=j.querySelector("ul.cbp-tm-submenu");if(k){j.className="cbp-tm-show";if(i._positionMenu(j)==="top"){j.className+=" cbp-tm-show-above"}else{j.className+=" cbp-tm-show-below"}}},this.touch?0:this.options.delayMenu)},_closeMenu:function(j){clearTimeout(this.omtimeout);var i=j.querySelector("ul.cbp-tm-submenu");if(i){j.className=j.className.replace(new RegExp("(^|\\s+)cbp-tm-show(\\s+|$)")," ");j.className=j.className.replace(new RegExp("(^|\\s+)cbp-tm-show-below(\\s+|$)")," ");j.className=j.className.replace(new RegExp("(^|\\s+)cbp-tm-show-above(\\s+|$)")," ")}},_handleClick:function(l,n){var m=l.parentNode,i=Array.prototype.slice.call(this.menuItems),k=m.querySelector("ul.cbp-tm-submenu");if(typeof this.current!=="undefined"&&i.indexOf(m)!==this.current){this._closeMenu(this.el.children[this.current]);this.el.children[this.current].querySelector("ul.cbp-tm-submenu").setAttribute("data-open","false")}if(k){n.preventDefault();var j=k.getAttribute("data-open");if(j==="true"){this._closeMenu(m);k.setAttribute("data-open","false")}else{this._openMenu(m);this.current=i.indexOf(m);k.setAttribute("data-open","true")}}},_positionMenu:function(j){var m=a(),k=f(j),i=k.top,l=m-i-j.offsetHeight;return(l<=i?"top":"bottom")}};d.cbpTooltipMenu=g})(window); -------------------------------------------------------------------------------- /js/modernizr.custom.js: -------------------------------------------------------------------------------- 1 | /* Modernizr 2.6.2 (Custom Build) | MIT & BSD 2 | * Build: http://modernizr.com/download/#-touch-shiv-cssclasses-teststyles-prefixes-load 3 | */ 4 | ;window.Modernizr=function(a,b,c){function w(a){j.cssText=a}function x(a,b){return w(m.join(a+";")+(b||""))}function y(a,b){return typeof a===b}function z(a,b){return!!~(""+a).indexOf(b)}function A(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:y(f,"function")?f.bind(d||b):f}return!1}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n={},o={},p={},q=[],r=q.slice,s,t=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["­",'"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},u={}.hasOwnProperty,v;!y(u,"undefined")&&!y(u.call,"undefined")?v=function(a,b){return u.call(a,b)}:v=function(a,b){return b in a&&y(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=r.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(r.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(r.call(arguments)))};return e}),n.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:t(["@media (",m.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c};for(var B in n)v(n,B)&&(s=B.toLowerCase(),e[s]=n[B](),q.push((e[s]?"":"no-")+s));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)v(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},w(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=m,e.testStyles=t,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+q.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f