#822 checkpoint. Integrated .mdb-layout-backdrop style, with a responsive .in visibility. JS classes added but not really functional yet. JS is mostly what is left - need to integrate a drawer toggle and cleanup the rest.

This commit is contained in:
Kevin Ross 2016-01-18 17:39:37 -06:00
parent 7c2fd40465
commit 79e7f1403b
11 changed files with 405 additions and 21 deletions

View File

@ -138,6 +138,7 @@ js: example.js
</ul> </ul>
</div> </div>
<main class="mdb-layout-content"> <main class="mdb-layout-content">
<div class="container"> <div class="container">
<div class="alert alert-info" role="alert"> <div class="alert alert-info" role="alert">

View File

@ -3,19 +3,12 @@ import Util from './util'
const Base = (($) => { const Base = (($) => {
const ClassName = { const ClassName = {
//FORM_GROUP: 'form-group',
MDB_FORM_GROUP: 'mdb-form-group', MDB_FORM_GROUP: 'mdb-form-group',
//MDB_LABEL: 'mdb-label',
//MDB_LABEL_STATIC: 'mdb-label-static',
//MDB_LABEL_PLACEHOLDER: 'mdb-label-placeholder',
//MDB_LABEL_FLOATING: 'mdb-label-floating',
//HAS_DANGER: 'has-danger',
IS_FILLED: 'is-filled', IS_FILLED: 'is-filled',
IS_FOCUSED: 'is-focused' IS_FOCUSED: 'is-focused'
} }
const Selector = { const Selector = {
//FORM_GROUP: `.${ClassName.FORM_GROUP}`,
MDB_FORM_GROUP: `.${ClassName.MDB_FORM_GROUP}` MDB_FORM_GROUP: `.${ClassName.MDB_FORM_GROUP}`
} }

55
js/src/baseLayout.js Normal file
View File

@ -0,0 +1,55 @@
import Base from './base'
import Util from './util'
const BaseLayout = (($) => {
const ClassName = {
CONTAINER: 'mdb-form-group'
}
const Selector = {
CONTAINER: `.${ClassName.CONTAINER}`
}
const Default = {}
/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/
class BaseLayout extends Base {
constructor($element, config, properties = {}) {
super($element, $.extend(true, {}, Default, config), properties)
}
dispose(dataKey) {
super.dispose(dataKey)
}
// ------------------------------------------------------------------------
// protected
// Find closest mdb-layout-container based on the given context
findLayoutContainer(raiseError = true, context = this.$element) {
let container = context.closest(Selector.CONTAINER)
if (container.length === 0 && raiseError) {
$.error(`Failed to find ${Selector.CONTAINER} for ${Util.describe(context)}`)
}
return container
}
// ------------------------------------------------------------------------
// private
// ------------------------------------------------------------------------
// static
}
return BaseLayout
})(jQuery)
export default BaseLayout

View File

@ -49,9 +49,15 @@ const BootstrapMaterialDesign = (($) => {
collapseInline: { collapseInline: {
selector: '.mdb-collapse-inline [data-toggle="collapse"]' selector: '.mdb-collapse-inline [data-toggle="collapse"]'
}, },
drawerToggle: {
selector: '[data-toggle="drawer"]'
},
file: { file: {
selector: 'input[type=file]' selector: 'input[type=file]'
}, },
layout: {
selector: '.mdb-layout-container'
},
radio: { radio: {
selector: '.radio > label > input[type=radio]' selector: '.radio > label > input[type=radio]'
}, },
@ -90,6 +96,8 @@ const BootstrapMaterialDesign = (($) => {
'checkbox', 'checkbox',
'checkboxInline', 'checkboxInline',
'collapseInline', 'collapseInline',
'layout',
'drawerToggle',
'file', 'file',
'radio', 'radio',
'radioInline', 'radioInline',

98
js/src/drawerToggle.js Normal file
View File

@ -0,0 +1,98 @@
import BaseLayout from './baseLayout'
import Util from './util'
const DrawerToggle = (($) => {
/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/
const NAME = 'drawerToggle'
const DATA_KEY = `mdb.${NAME}`
const JQUERY_NAME = `mdb${NAME.charAt(0).toUpperCase() + NAME.slice(1)}`
const JQUERY_NO_CONFLICT = $.fn[JQUERY_NAME]
const ClassName = {
//IN: 'in',
DRAWER: 'mdb-layout-drawer',
CONTAINER: 'mdb-layout-container'
//COLLAPSING: 'collapsing',
//COLLAPSED: 'collapsed',
//WIDTH: 'width'
}
//const Selector = {
// CONTAINER: `.${ClassName.CONTAINER}`
//}
const Default = {}
/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/
class DrawerToggle extends BaseLayout {
// $element is expected to be the trigger
// i.e. <button class="btn mdb-btn-icon" for="search" data-toggle="drawer" data-target="#my-side-nav-drawer" aria-expanded="false" aria-controls="my-side-nav-drawer">
constructor($element, config) {
super($element, $.extend(true, {}, Default, config))
let selector = $element.data('target')
this.$drawer = $(selector)
Util.assert($element, this.$drawer.length === 0, `Cannot find drawer target for ${Util.describe($element)}`)
Util.assert(this.$drawer, !this.$drawer.hasClass(ClassName.DRAWER), `${Util.describe(this.$drawer)} is expected to have the '${ClassName.DRAWER}' class. It is being targeted by ${Util.describe($element)}`)
// find the drawer's container - remember, this button may be outside the container, we only need the target's container.
this.$layoutContainer = this.findLayoutContainer(true, this.$drawer)
// get a handle to the Layout object and interact with it? i.e. show/hide?
}
dispose() {
super.dispose(DATA_KEY)
this.$drawer = null
this.$layoutContainer = null
}
// ------------------------------------------------------------------------
// private
// ------------------------------------------------------------------------
// static
static _jQueryInterface(config) {
return this.each(function () {
let $element = $(this)
let data = $element.data(DATA_KEY)
if (!data) {
data = new DrawerToggle($element, config)
$element.data(DATA_KEY, data)
}
})
}
}
/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/
$.fn[JQUERY_NAME] = DrawerToggle._jQueryInterface
$.fn[JQUERY_NAME].Constructor = DrawerToggle
$.fn[JQUERY_NAME].noConflict = () => {
$.fn[JQUERY_NAME] = JQUERY_NO_CONFLICT
return DrawerToggle._jQueryInterface
}
return DrawerToggle
})(jQuery)
export default DrawerToggle

View File

@ -22,6 +22,9 @@ import Switch from './switch'
import Text from './text' import Text from './text'
import Textarea from './textarea' import Textarea from './textarea'
import Layout from './layout'
import DrawerToggle from './drawerToggle'
import Ripples from './ripples' import Ripples from './ripples'
import Autofill from './autofill' import Autofill from './autofill'
import BootstrapMaterialDesign from './bootstrapMaterialDesign' import BootstrapMaterialDesign from './bootstrapMaterialDesign'

186
js/src/layout.js Normal file
View File

@ -0,0 +1,186 @@
import BaseLayout from './baseLayout'
const Layout = (($) => {
/**
* ------------------------------------------------------------------------
* Constants
* ------------------------------------------------------------------------
*/
const NAME = 'layout'
const DATA_KEY = `mdb.${NAME}`
const JQUERY_NAME = `mdb${NAME.charAt(0).toUpperCase() + NAME.slice(1)}`
const JQUERY_NO_CONFLICT = $.fn[JQUERY_NAME]
const Keycodes = {
ENTER: 13,
ESCAPE: 27,
SPACE: 32
}
const ClassName = {
CANVAS: 'mdb-layout-canvas',
HEADER: 'mdb-layout-header',
DRAWER: 'mdb-layout-drawer',
CONTENT: 'mdb-layout-content',
DRAWER_BTN: 'mdb-layout-drawer-button', // FIXME: swithch to data-drawer attr finder or something like that, see navbar toggler
BACKDROP: 'mdb-layout-backdrop'
}
const Selector = {
DRAWER_BTN: `.${ClassName.DRAWER_BTN}`,
DRAWER: `.${ClassName.DRAWER}`,
HEADER: `.${ClassName.HEADER}`,
CONTENT: `.${ClassName.CONTENT}`,
DATA_TOGGLE_DRAWER: '[data-toggle="drawer"]'
}
const Default = {}
/**
* ------------------------------------------------------------------------
* Class Definition
* ------------------------------------------------------------------------
*/
class Layout extends BaseLayout {
constructor($element, config) {
super($element, $.extend(true, {}, Default, config))
// FIXME: I'm not sure we want to auto-resolve a canvas....think about it and refactor this or delete it.
// FIXME: with a goal of supporting two drawers, or even more, I'm not sure we want to auto-add the canvas.
//var canvas = document.createElement('div')
//canvas.addClass(ClassName.CANVAS)
//this.$element.parentElement.insertBefore(canvas, this.$element)
//this.$element.parentElement.removeChild(this.$element)
//canvas.appendChild(this.$element)
this.$header = $element.find(`> ${Selector.HEADER}`)
this.$drawer = $element.find(`> ${Selector.DRAWER}`)
this.$content = $element.find(`> ${Selector.CONTENT}`)
// Add drawer toggling button to our layout, if we have an openable drawer.
if (this.$drawer) {
// FIXME: separate DrawerToggle component?
//this.$drawerBtn = $element.find(`${DRAWER_BTN}`)
//
//if (this.$drawerBtn) { // FIXME what about many drawer buttons? implies a separate jquery class
//
// this.$drawerBtn.click((ev) => {
// this._drawerToggleHandler(ev)
// })
// this.$drawerBtn.keydown((ev) => {
// this._drawerToggleHandler(ev)
// })
//}
// create the backdrop
this.$backdrop = $(`<div class="${ClassName.BACKDROP}"></div>`)
this.$backdrop.click((ev) => {
this._drawerToggleHandler(ev)
})
this.$element.append(this.$backdrop)
this.$drawer.keydown((ev) => {
this._onDrawerKeydown(ev)
})
this.$drawer.attr('aria-hidden', 'true')
}
}
dispose() {
super.dispose(DATA_KEY)
}
/**
* Toggle drawer state
*/
toggleDrawer() {
//FIXME: seems terrible, look at navbar toggler
//$drawerBtn = this.$element.querySelector(Selector.DRAWER_BTN)
//var firstLink = document.querySelector(Selector.DRAWER + ' a')
//this.$drawer.classList.toggle(ClassName.IS_DRAWER_OPEN)
//this.$backdrop.classList.toggle(ClassName.IS_DRAWER_OPEN)
//
//// focus first link if drawer will be opened otherwise focus the drawer button
//if (this.$drawer.hasClass(ClassName.IS_DRAWER_OPEN)) {
// this.$drawer.attr('aria-hidden', 'false')
// this.$drawerBtn.attr('aria-expanded', 'true')
// if (firstLink) {
// firstLink.focus()
// }
//} else {
// this.$drawer.attr('aria-hidden', 'true')
// this.$drawerBtn.attr('aria-expanded', 'false')
// this.$drawerBtn.focus()
//}
}
// ------------------------------------------------------------------------
// private
/**
* Handles events of of drawer button.
*
* @param {Event} ev The event that fired.
* @private
*/
_drawerToggleHandler(ev) {
if (ev && (ev.type === 'keydown')) {
if (ev.keyCode === Keycodes.SPACE || ev.keyCode === Keycodes.ENTER) {
// prevent scrolling in drawer nav
ev.preventDefault()
} else {
// prevent other keys
return
}
}
this.toggleDrawer()
}
/**
* Handles a keyboard event on the drawer.
*/
_onDrawerKeydown(ev) {
if (ev.keyCode === Keycodes.ESCAPE) {
this.toggleDrawer()
}
}
// ------------------------------------------------------------------------
// static
static _jQueryInterface(config) {
return this.each(function () {
let $element = $(this)
let data = $element.data(DATA_KEY)
if (!data) {
data = new Layout($element, config)
$element.data(DATA_KEY, data)
}
})
}
}
/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
*/
$.fn[JQUERY_NAME] = Layout._jQueryInterface
$.fn[JQUERY_NAME].Constructor = Layout
$.fn[JQUERY_NAME].noConflict = () => {
$.fn[JQUERY_NAME] = JQUERY_NO_CONFLICT
return Layout._jQueryInterface
}
return Layout
})(jQuery)
export default Layout

View File

@ -3,11 +3,10 @@
// mdb-layout-content that scrolls. // mdb-layout-content that scrolls.
// First element // First element
.mdb-layout-canvas { .mdb-layout-canvas { // added by js?
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
// Primary layout container, belongs inside a mdb-layout-canvas. // Primary layout container, belongs inside a mdb-layout-canvas.
@ -51,3 +50,26 @@
flex-grow: 1; flex-grow: 1;
} }
// Backdrop
.mdb-layout-backdrop {
position: absolute;
top: 0;
left: 0;
z-index: 4;
width: 100%;
height: 100%;
visibility: hidden;
background-color: transparent;
transition-property: background-color;
@include material-animation-default();
@supports (pointer-events: auto) {
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
transition-property: opacity;
visibility: visible;
pointer-events: none;
}
// NOTE: the &.in style is responsive, generated by @mixin mdb-layout-overlay-backdrop-in() where needed.
}

View File

@ -2,6 +2,7 @@
@import "mixins/breakpoints"; @import "mixins/breakpoints";
@import "mixins/animations"; @import "mixins/animations";
@import "mixins/type"; @import "mixins/type";
@import "mixins/layout";
@import "mixins/drawer"; @import "mixins/drawer";
@import "mixins/shadows"; @import "mixins/shadows";
@import "mixins/variations"; @import "mixins/variations";

View File

@ -91,20 +91,17 @@
&.mdb-drawer-fixed-#{$side} { &.mdb-drawer-fixed-#{$side} {
// Push - drawer will push the header and content (default behavior) // Push - drawer will push the header and content (default behavior)
&, > .mdb-layout-header {
&.mdb-drawer-push { width: calc(100% - #{$size});
> .mdb-layout-header { margin-#{$side}: $size;
width: calc(100% - #{$size}); }
margin-#{$side}: $size;
}
> .mdb-layout-drawer { > .mdb-layout-drawer {
transform: translateX(0); transform: translateX(0);
} }
> .mdb-layout-content { > .mdb-layout-content {
margin-#{$side}: $size; margin-#{$side}: $size;
}
} }
} }
} }
@ -181,6 +178,8 @@
} }
@mixin mdb-drawer-x-overlay() { @mixin mdb-drawer-x-overlay() {
@include mdb-layout-overlay-backdrop-in();
@each $side in (left right) { @each $side in (left right) {
&.mdb-drawer-fixed-#{$side} { &.mdb-drawer-fixed-#{$side} {
> .mdb-layout-header, > .mdb-layout-header,
@ -193,6 +192,8 @@
} }
@mixin mdb-drawer-y-overlay() { @mixin mdb-drawer-y-overlay() {
@include mdb-layout-overlay-backdrop-in();
@each $side in (top bottom) { @each $side in (top bottom) {
&.mdb-drawer-fixed-#{$side} { &.mdb-drawer-fixed-#{$side} {
> .mdb-layout-header { > .mdb-layout-header {

16
scss/mixins/_layout.scss Normal file
View File

@ -0,0 +1,16 @@
@mixin mdb-layout-overlay-backdrop-in() {
> .mdb-layout-backdrop {
.in {
visibility: visible;
background-color: rgba(0, 0, 0, 0.5);
}
@supports (pointer-events: auto) {
&.in {
pointer-events: auto;
opacity: 1;
}
}
}
}