ion panels!

This commit is contained in:
Adam Bradley
2013-08-28 12:28:44 -05:00
parent 75da07249f
commit a8ad16df86
7 changed files with 98 additions and 170 deletions

12
dist/framework.css vendored
View File

@ -221,7 +221,7 @@ a.list-item {
margin-bottom: 0; margin-bottom: 0;
line-height: 1.3; } line-height: 1.3; }
[data-panel] { .ion-panel {
display: none; display: none;
min-height: 100%; min-height: 100%;
max-height: 100%; max-height: 100%;
@ -229,7 +229,7 @@ a.list-item {
top: 0; top: 0;
z-index: 0; } z-index: 0; }
.panel-active { .ion-panel-active {
display: block; display: block;
width: 270px; } width: 270px; }
@ -244,9 +244,9 @@ header, main, footer {
-moz-transform: translate3d(0, 0, 0); -moz-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0); } transform: translate3d(0, 0, 0); }
.panel-opened > section > header, .ion-panel-opened > section > header,
.panel-opened > section > main, .ion-panel-opened > section > main,
.panel-opened > section > footer { .ion-panel-opened > section > footer {
-webkit-transform: translate3d(270px, 0, 0); -webkit-transform: translate3d(270px, 0, 0);
-moz-transform: translate3d(270px, 0, 0); -moz-transform: translate3d(270px, 0, 0);
transform: translate3d(270px, 0, 0); } transform: translate3d(270px, 0, 0); }
@ -534,7 +534,7 @@ main {
a.list-item { a.list-item {
color: #333333; } color: #333333; }
[data-panel] { .ion-panel {
background: #eeeeee; background: #eeeeee;
border-right: 1px solid #bbbbbb; } border-right: 1px solid #bbbbbb; }

View File

@ -30,15 +30,16 @@
</section> </section>
<section data-panel="my-left-panel"> <section id="my-left-panel" class="ion-panel">
This is my default left side panel! This is my default left side panel!
</section> </section>
<section data-panel="my-other-left-panel"> <section id="my-other-left-panel" class="ion-panel">
This is my other left side panel! This is my other left side panel!
</section> </section>
<script src="../../js/framework/framework-panel.js"></script> <script src="../../js/framework/framework-panel.js"></script>
<script src="../../js/framework/helpers/panel-helper.js"></script>
</body> </body>
</html> </html>

View File

@ -1,153 +0,0 @@
(function(window, document, framework) {
var
x,
lockInWidthStyles,
isLockInWidthSet,
isPanelOpen,
panelReferences = {},
timeout,
className,
PANEL_ACTIVE = "panel-active",
PANEL_OPENED = "panel-opened";
function click(e) {
if(e.target.dataset.togglePanel) {
logEvent("click");
if(isPanelOpen) {
// there's a panel open, close it if the page location changed
closePanel();
} else {
openPanel(e.target.dataset.togglePanel);
}
return true;
}
}
function touchEnd(e) {
if(click(e)) {
e.preventDefault();
e.stopPropagation();
return false;
}
}
function autoClose() {
if(isPanelOpen) {
logEvent("autoClose");
// there's a panel open, close it if the page location changed
closePanel();
}
}
function openPanel(panelId) {
logEvent("openPanel: " + panelId);
// see if there is an element with this id
var panel = getPanelElement(panelId);
if(panel) {
// this element is a panel, open it!
// find all the panels that are or were active
var panelsActive = document.getElementsByClassName(PANEL_ACTIVE);
// remove the panel-active css classes from each of the previously opened panels
for(x=0; x<panelsActive.length; x++) {
className = panelsActive[x].className.replace(PANEL_ACTIVE, "").trim();
panelsActive[x].className = className;
}
// open the panel we want open by adding the panel-active css classes
panel.className += " " + PANEL_ACTIVE;
// manually lock in all the widths of the page which the panel will slide over
// do all of this in one DOM manipulation
// This makes it easy to modify all of the elements in one call,
// and also undo all of the element widths in one call
// the css added below makes something like: #my-panel ~ * {width: 420px !important}
// basically any sibling elements to the panel should lock in the document width
setLockInWidthStyles();
// add to <body> that a panel is open
document.body.className += " " + PANEL_OPENED;
// remember that a panel is currently open
isPanelOpen = true;
}
}
function closePanel() {
logEvent("closePanel");
// there is a panel already open, so close it
isPanelOpen = false;
// note: do not remove the panel-active class from panel
// the panel should stay displayed as it panel closes
// find the element with panel-open class
var openedPanels = document.getElementsByClassName(PANEL_OPENED);
// remove the panel-opened css classes from each of the previously opened panels
for(x=0; x<openedPanels.length; x++) {
// if this panel is the same last opened panel then don't remove the css class yet
className = openedPanels[x].className.replace(PANEL_OPENED, "").trim();
openedPanels[x].className = className;
}
// remove from <body> that no panels should be open
className = document.body.className.replace(PANEL_OPENED, "").trim();
document.body.className = className;
// remove the locked in widths
timeout = setTimeout(removeLockInWidthStyles, 300);
}
function setLockInWidthStyles() {
if(isLockInWidthSet) return;
clearTimeout(timeout);
var styles = "section>header,section>main,section>footer {width:" + document.width + "px !important}";
if(!lockInWidthStyles) {
lockInWidthStyles = document.createElement("style");
lockInWidthStyles.innerHTML = styles;
document.head.appendChild(lockInWidthStyles);
} else {
lockInWidthStyles.innerHTML = styles;
}
isLockInWidthSet = true;
}
function removeLockInWidthStyles() {
lockInWidthStyles.innerHTML = "";
isLockInWidthSet = false;
}
function getPanelElement(panelId) {
// used to minimize DOM lookups
if( !panelReferences[panelId] ) {
panelReferences[panelId] = document.querySelector( "[data-panel='" + panelId + "']" );
}
return panelReferences[panelId];
}
var logEvent = function(data) {
var e = document.getElementById('event-log');
var l = document.createElement('div');
l.innerHTML = data;
if(e.childNodes.length > 10) {
e.innerHTML = "";
}
e.appendChild(l);
}
window.addEventListener('click', click, false);
window.addEventListener('touchend', touchEnd, false);
window.addEventListener("resize", autoClose, false);
window.addEventListener("popstate", autoClose, false);
})(this, document, FM = this.FM || {});

View File

@ -0,0 +1,21 @@
(function(window, document, ion) {
function click(e) {
if(e.target.dataset.togglePanel) {
ion.Panel.toggle(e.target.dataset.togglePanel);
return true;
}
}
function touchEnd(e) {
if(click(e)) {
e.preventDefault();
e.stopPropagation();
return false;
}
}
window.addEventListener('click', click, false);
window.addEventListener('touchend', touchEnd, false);
})(this, document, ion = this.ion || {});

59
js/framework/ion-panel.js Normal file
View File

@ -0,0 +1,59 @@
(function(window, document, ion) {
var
x,
isPanelOpen,
PANEL_ACTIVE = "ion-panel-active",
PANEL_OPENED = "ion-panel-opened";
ion.Panel = {
toggle: function(panelId) {
if(isPanelOpen) {
this.close();
} else {
this.open(panelId);
}
},
open: function(panelId) {
// see if there is an element with this id
var panel = document.getElementById(panelId);
if(panel) {
// this element is a panel, open it!
// remember that a panel is currently open
isPanelOpen = true;
// find all the panels that are or were once active
var panelsActive = document.getElementsByClassName(PANEL_ACTIVE);
// remove the panel-active css classes from each of the previously active panels
for(x=0; x<panelsActive.length; x++) {
panelsActive[x].className = panelsActive[x].className.replace(PANEL_ACTIVE, "").trim();
}
// activate the panel we want open by adding the panel-active css classes
panel.className += " " + PANEL_ACTIVE;
// add to <body> that there is a panel open
document.body.className += " " + PANEL_OPENED;
}
},
close: function() {
if(isPanelOpen) {
// there is a panel already open, so close it
isPanelOpen = false;
// remove from <body> so that no panels should be open
document.body.className = document.body.className.replace(PANEL_OPENED, "").trim();
}
}
};
window.addEventListener("popstate", ion.Panel.close, false);
})(this, document, ion = this.ion || {});

View File

@ -1,5 +1,5 @@
[data-panel] { .ion-panel {
display: none; display: none;
min-height: 100%; min-height: 100%;
max-height: 100%; max-height: 100%;
@ -7,7 +7,7 @@
top: 0; top: 0;
z-index: 0; z-index: 0;
} }
.panel-active { .ion-panel-active {
display: block; display: block;
width: $panelOpenWidth; width: $panelOpenWidth;
} }
@ -26,11 +26,11 @@ header, main, footer {
transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);
} }
.panel-opened > section > header, .ion-panel-opened > section > header,
.panel-opened > section > main, .ion-panel-opened > section > main,
.panel-opened > section > footer .ion-panel-opened > section > footer
{ {
-webkit-transform: translate3d($panelOpenWidth, 0,0 ); -webkit-transform: translate3d($panelOpenWidth, 0,0 );
-moz-transform: translate3d($panelOpenWidth, 0,0 ); -moz-transform: translate3d($panelOpenWidth, 0,0 );
transform: translate3d($panelOpenWidth, 0,0 ); transform: translate3d($panelOpenWidth, 0,0 );
} }

View File

@ -1,5 +1,5 @@
[data-panel] { .ion-panel {
background: $panelBackgroundColor; background: $panelBackgroundColor;
border-right: 1px solid $panelInsetBorderColor; border-right: 1px solid $panelInsetBorderColor;
} }