mirror of https://github.com/twbs/ratchet.git
Browse Source
Based on the `modals` component. See example at http://michaelrienstra.com/temporary/ratchet/side-menus.html The current implementation relies on putting a wrapper (`<div class="side-menu-siblings-wrapper">`) around the `side-menu`s siblings (`<header class="bar">` & `<div class="content">`). I have working code to handle the wrapping of siblings automatically, as well as working code that works without the wrapper (but I realized I was going to have to add more "moving bits" to get the subtle drop shadow to animate without the wrapper). Minimally tested on Android (Nexus 4) & iOS (iPhone 5). Happy to do more testing / etc. if this component is of interest. Attribution: I borrowed a few lines of CSS from http://mmenu.frebsite.nl/ (which is dual licensed under the MIT and GPL licenses).pull/551/head
Michael Rienstra
11 years ago
2 changed files with 123 additions and 0 deletions
@ -0,0 +1,74 @@
|
||||
/* ======================================================================== |
||||
* Ratchet: side-menus.js v2.0.2 |
||||
* http://goratchet.com/components#sideMenus
|
||||
* ======================================================================== |
||||
* Copyright 2014 Connor Sears |
||||
* Licensed under MIT (https://github.com/twbs/ratchet/blob/master/LICENSE)
|
||||
* ======================================================================== */ |
||||
|
||||
!(function () { |
||||
'use strict'; |
||||
|
||||
var findSideMenus = function (target) { |
||||
var i; |
||||
var sideMenus = document.querySelectorAll('a'); |
||||
|
||||
for (; target && target !== document; target = target.parentNode) { |
||||
for (i = sideMenus.length; i--;) { |
||||
if (sideMenus[i] === target) { |
||||
return target; |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
|
||||
var getSideMenu = function (event) { |
||||
var sideMenuToggle = findSideMenus(event.target); |
||||
if (sideMenuToggle && sideMenuToggle.hash) { |
||||
var sideMenu = document.querySelector(sideMenuToggle.hash); |
||||
if (sideMenu && sideMenu.classList.contains('side-menu')) { |
||||
return sideMenu; |
||||
} |
||||
} |
||||
}; |
||||
|
||||
var getSideMenuSiblings = function (sideMenu) { |
||||
var siblings = [].slice.call(sideMenu.parentNode.children); |
||||
siblings = siblings.filter(function(val) { |
||||
return [sideMenu].indexOf(val) === -1 && val.nodeName !== 'SCRIPT'; |
||||
}); |
||||
return siblings; |
||||
}; |
||||
|
||||
window.addEventListener('touchend', function (event) { |
||||
var sideMenu = getSideMenu(event); |
||||
if (sideMenu) { |
||||
var siblings = getSideMenuSiblings(sideMenu); |
||||
var i; |
||||
var l; |
||||
var hasBlocker = false; |
||||
for (i = 0, l = siblings.length; i < l; i++) { |
||||
if (!hasBlocker && siblings[i].classList.contains('side-menu-blocker')) { |
||||
hasBlocker = true; |
||||
} |
||||
if (siblings[i].classList.contains('activeSideMenu')) { |
||||
siblings[i].classList.remove('activeSideMenu'); |
||||
siblings[i].classList.add('inactiveSideMenu'); |
||||
} else { |
||||
siblings[i].classList.remove('inactiveSideMenu'); |
||||
siblings[i].classList.add('activeSideMenu'); |
||||
} |
||||
} |
||||
if (hasBlocker === false) { |
||||
var blocker = document.createElement('a'); |
||||
blocker.href = '#' + sideMenu.id; |
||||
blocker.classList.add('side-menu-blocker'); |
||||
sideMenu.parentElement.appendChild(blocker); |
||||
siblings.push(blocker); |
||||
blocker.classList.add('activeSideMenu'); |
||||
} |
||||
|
||||
event.preventDefault(); // prevents rewriting url (apps can still use hash values in url)
|
||||
} |
||||
}); |
||||
}()); |
@ -0,0 +1,49 @@
|
||||
// |
||||
// Side menus |
||||
// -------------------------------------------------- |
||||
|
||||
.side-menu { |
||||
position: fixed; |
||||
top: 0; |
||||
z-index: -1; |
||||
width: 80%; |
||||
height: 100%; |
||||
} |
||||
|
||||
.side-menu-blocker { |
||||
background: url(data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==) transparent; |
||||
display: none; |
||||
width: 100%; |
||||
height: 100%; |
||||
position: fixed; |
||||
top: 0; |
||||
z-index: 999999; |
||||
|
||||
&.activeSideMenu { |
||||
display: block; |
||||
box-shadow: none; |
||||
} |
||||
} |
||||
|
||||
.side-menu-siblings-wrapper { |
||||
width: 100%; |
||||
height: 100%; |
||||
/* Alternate approach, as per BODY: |
||||
position: fixed; |
||||
top: 0; |
||||
right: 0; |
||||
bottom: 0; |
||||
left: 0; |
||||
*/ |
||||
} |
||||
|
||||
.inactiveSideMenu, .activeSideMenu { |
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5); |
||||
-webkit-transition: -webkit-transform .4s; |
||||
-moz-transition: -moz-transform .4s; |
||||
transition: transform .4s; |
||||
@include transform(translate3d(0, 0, 0)); |
||||
} |
||||
.activeSideMenu { |
||||
@include transform(translate3d(80%, 0, 0)); |
||||
} |
Loading…
Reference in new issue