Project import generated by Copybara.
GitOrigin-RevId: 63746295f1a5ab5a619056791995793d65529e62
diff --git a/node_modules/mdl-ext/src/_functions.scss b/node_modules/mdl-ext/src/_functions.scss
new file mode 100644
index 0000000..2571fec
--- /dev/null
+++ b/node_modules/mdl-ext/src/_functions.scss
@@ -0,0 +1,302 @@
+///
+/// Returns the opposite direction of each direction in a list
+/// Modified from: https://css-tricks.com/snippets/sass/opposite-direction-function/
+/// @author Hugo Giraudel
+/// @param {List} $directions - List of initial directions
+/// @return {List} - List of opposite directions
+@function mdlext-opposite-direction($directions) {
+ $opposite-directions: ();
+ $direction-map: (
+ 'top': 'bottom',
+ 'right': 'left',
+ 'bottom': 'top',
+ 'left': 'right',
+ 'center': 'center',
+ 'ltr': 'rtl',
+ 'rtl': 'ltr'
+ );
+
+ @each $direction in $directions {
+ $direction: to-lower-case($direction);
+
+ @if map-has-key($direction-map, $direction) {
+ $opposite-directions: append($opposite-directions, unquote(map-get($direction-map, $direction)));
+ }
+ @else {
+ @warn "No opposite direction can be found for `#{$direction}`. Direction omitted.";
+ }
+ }
+
+ @return $opposite-directions;
+}
+
+///
+/// Strip unit from value
+/// @author Hugo Giraudel
+/// http://hugogiraudel.com/2013/08/12/sass-functions/
+/// https://css-tricks.com/snippets/sass/strip-unit-function/
+/// @param {Number} $number - Number to remove unit from
+/// @return {Number} - Unitless number
+
+@function strip-unit($number) {
+ @return if(type-of($number) == 'number' and not unitless($number), $number / ($number * 0 + 1), $number);
+}
+
+///
+/// Clamping a number means restricting it between min and max values.
+/// 4 clamped to 1-3 equals 3.
+/// -5 clamped to 1-10 equals 1.
+/// 42 clamped to 10-100 equals 42.
+/// @author Hugo Giraudel
+/// http://hugogiraudel.com/2013/08/12/sass-functions/
+/// @param {Number} $value - The value to clamp
+/// @param {Number} $min - min value in range
+/// @param {Number} $max - Max value in range
+/// @return {Number} - The clamped value
+
+@function clamp($value, $min, $max) {
+ @return if($value > $max, $max, if($value < $min, $min, $value));
+}
+
+///
+/// Convert one unit into another
+/// @author Hugo Giraudel
+/// http://www.sitepoint.com/understanding-sass-units/
+/// @param {Number} $value - Initial value
+/// @param {String} $unit - Desired unit
+/// @return {Number}
+/// @throw Error if `$unit` does not exist or if units are incompatible.
+
+/* stylelint-disable */
+@function convert-unit($value, $unit) {
+ $units: (
+ 'px' : 0px,
+ 'cm' : 0cm,
+ 'mm' : 0mm,
+ '%' : 0%,
+ 'ch' : 0ch,
+ 'in' : 0in,
+ 'em' : 0em,
+ 'rem' : 0rem,
+ 'pt' : 0pt,
+ 'pc' : 0pc,
+ 'ex' : 0ex,
+ 'vw' : 0vw,
+ 'vh' : 0vh,
+ 'vmin': 0vmin,
+ 'vmax': 0vmax,
+ 'deg' : 0deg,
+ 'turn': 0turn,
+ 'rad' : 0rad,
+ 'grad': 0grad,
+ 's' : 0s,
+ 'ms' : 0ms,
+ 'Hz' : 0Hz,
+ 'kHz' : 0kHz,
+ 'dppx': 0dppx,
+ 'dpcm': 0dpcm,
+ 'dpi' : 0dpi,
+ );
+
+ @if map-has-key($units, $unit) {
+ @return map-get($units, $unit) + $value;
+ }
+
+ @error "Unknown unit `#{$unit}`.";
+}
+/* stylelint-enable */
+
+
+///
+/// Replace `$search` with `$replace` in `$string`
+/// @author Hugo Giraudel, http://hugogiraudel.com/2014/01/13/sass-string-replacement-function/
+/// @param {String} $string - Initial string
+/// @param {String} $search - Substring to replace
+/// @param {String} $replace ('') - New value
+/// @return {String} - Updated string
+@function str-replace($string, $search, $replace: '') {
+ $index: str-index($string, $search);
+
+ @if $index {
+ @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
+ }
+ @return $string;
+}
+
+///
+/// @function explode() -- split a string into a list of strings
+/// @author https://gist.github.com/danielpchen/3677421ea15dcf2579ff
+/// {string} $string: the string to be split
+/// {string} $delimiter: the boundary string
+/// @return {list} the result list
+@function explode($string, $delimiter: ',') {
+ $result: ();
+ @if $delimiter == "" {
+ @for $i from 1 through str-length($string) {
+ $result: append($result, str-slice($string, $i, $i));
+ }
+ @return $result;
+ }
+ $exploding: true;
+ @while $exploding {
+ $d-index: str-index($string, $delimiter);
+ @if $d-index {
+ @if $d-index > 1 {
+ $result: append($result, str-slice($string, 1, $d-index - 1));
+ $string: str-slice($string, $d-index + str-length($delimiter));
+ }
+ @else if $d-index == 1 {
+ $string: str-slice($string, 1, $d-index + str-length($delimiter));
+ }
+ @else {
+ $result: append($result, $string);
+ $exploding: false;
+ }
+ }
+ @else {
+ $result: append($result, $string);
+ $exploding: false;
+ }
+ }
+ @return $result;
+}
+
+///
+/// Add `$unit` to `$value`
+/// @author Hugo Giraudel
+///
+/// @param {Number} $value - Value to add unit to
+/// @param {String} $unit - String representation of the unit
+///
+/// @return {Number} - `$value` expressed in `$unit`
+/// @throw Error if `$unit` does not exist or if units are incompatible.
+///
+@function to-length($value, $unit) {
+ $units: (
+ 'px' : 1px,
+ 'cm' : 1cm,
+ 'mm' : 1mm,
+ '%' : 1%,
+ 'ch' : 1ch,
+ 'pc' : 1pc,
+ 'in' : 1in,
+ 'em' : 1em,
+ 'rem' : 1rem,
+ 'pt' : 1pt,
+ 'ex' : 1ex,
+ 'vw' : 1vw,
+ 'vh' : 1vh,
+ 'vmin': 1vmin,
+ 'vmax': 1vmax
+ );
+
+ @if not index(map-keys($units), $unit) {
+ @error('Invalid unit `#{$unit}`.');
+ }
+
+ @return $value * map-get($units, $unit);
+}
+
+///
+/// Casts a string into a number
+///
+/// @author Hugo Giraudel
+// @param {String | Number} $value - Value to be parsed
+///
+/// @return {Number}
+/// @throw Error if `$value` is not a number or a string.
+///
+@function to-number($value) {
+ @if type-of($value) == 'number' {
+ @return $value;
+ }
+ @else if type-of($value) != 'string' {
+ @error('Value for `to-number` should be a number or a string.');
+ }
+
+ $result: 0;
+ $digits: 0;
+ $minus: str-slice($value, 1, 1) == '-';
+ $numbers: ('0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9);
+
+ @for $i from if($minus, 2, 1) through str-length($value) {
+ $character: str-slice($value, $i, $i);
+
+ @if not (index(map-keys($numbers), $character) or $character == '.') {
+ @return to-length(if($minus, -$result, $result), str-slice($value, $i));
+ }
+
+ @if $character == '.' {
+ $digits: 1;
+ }
+ @else if $digits == 0 {
+ $result: $result * 10 + map-get($numbers, $character);
+ }
+ @else {
+ $digits: $digits * 10;
+ $result: $result + map-get($numbers, $character) / $digits;
+ }
+ }
+
+ @return if($minus, -$result, $result);
+}
+
+///
+/// Convert `$rgb-string` to a number list
+/// @author Leif Olsen
+/// @param {String | Number} $value - Value to be parsed
+/// @return {list} the rgb number list
+/// @throw Error if `$value` is not a number, color or a string.
+@function rgb-string-to-numbers($value) {
+ @if type-of($value) == 'number' or type-of($value) == 'color' {
+ @return $value;
+ }
+ @else if type-of($value) != 'string' {
+ @error('Value for `rgb-string-to-numbers` should be a number or a string.');
+ }
+
+ $s: str-replace($value, "rgba");
+ $s: str-replace($s, "rgb");
+ $s: str-replace($s, "(");
+ $s: str-replace($s, ")");
+ $s: str-replace($s, " ");
+ $l: explode($s);
+ $result: ();
+ @for $i from 1 through length($l) {
+ $result: append($result, to-number(nth($l, $i)));
+ }
+ @return $result;
+}
+
+///
+/// Convert `$rgb-string` to a corresponding hex value
+/// @author Leif Olsen
+/// @param {String | Number} $value - Value to be parsed
+/// @return {number} the rgb hex value
+/// @throw Error if `$value` is not a number, color or a string.
+@function rgb-string-to-hex($value) {
+ @if type-of($value) == 'number' or type-of($value) == 'color' {
+ @return $value;
+ }
+ @else if type-of($value) != 'string' {
+ @error('Value for `rgb-string-to-numbers` should be a number or a string.');
+ }
+ $l: rgb-string-to-numbers($value);
+ @return rgb(nth($l, 1), nth($l, 2), nth($l, 3));
+}
+
+
+///
+/// Convert hex color to a coresponding `$rgb-string`
+/// @author https://github.com/google/material-design-lite/issues/1689
+/// @param {Number} $hexColor - Value to convert
+/// @return {String} the rgb string value
+///
+/// @example - $color-primary: hex-to-string(#333);
+@function hex-to-rgb-string($hexColor) {
+ // 0.999999 val in alpha actually compiles to 1.0
+ $rgbaVal: inspect(rgba($hexColor, 0.9999999));
+
+ // slice substring between 'rgba(' and '1.0)'
+ @return str-slice($rgbaVal, 6, str-length($rgbaVal)-4);
+}
diff --git a/node_modules/mdl-ext/src/_mixins.scss b/node_modules/mdl-ext/src/_mixins.scss
new file mode 100644
index 0000000..cf274ab
--- /dev/null
+++ b/node_modules/mdl-ext/src/_mixins.scss
@@ -0,0 +1,211 @@
+@import "functions";
+
+/// Triangle helper mixin
+/// Modified from: http://blustemy.io/drawing-pure-css-arrows-with-mixins/
+/// https://css-tricks.com/snippets/sass/css-triangle-mixin/
+/// @param {Direction} $direction - Triangle direction, either `top`, `right`, `bottom` or `left`
+/// @param {Color} $color [currentcolor] - Triangle color
+/// @param {Length} $size [1em] - Triangle size
+@mixin mdlext-arrow($direction: bottom, $base-width: 15px, $length: 10px, $color: inherit, $font-size: inherit) {
+ content: '';
+ width: 0;
+ height: 0;
+ font-size: $font-size;
+ line-height: $font-size;
+ border-#{mdlext-opposite-direction($direction)}: $length solid $color;
+ border-#{mdlext-opposite-direction($direction)}-width: $length;
+ border-#{mdlext-opposite-direction($direction)}-style: solid;
+ border-#{mdlext-opposite-direction($direction)}-color: $color;
+
+ $perpendicular-borders: ($base-width / 2) solid transparent;
+
+ @if $direction == top or $direction == bottom {
+ border-left: $perpendicular-borders;
+ border-right: $perpendicular-borders;
+ }
+ @else if $direction == right or $direction == left {
+ border-bottom: $perpendicular-borders;
+ border-top: $perpendicular-borders;
+ }
+}
+
+/// Hide element while making it readable for screen readers
+/// Copied from HTML5Boilerplate:
+/// https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css#L119-L133
+@mixin mdlext-visually-hidden() {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px;
+}
+
+
+/// Toggle for aria-expanded attribute
+///
+/// @author Leif Olsen
+/// @param {Font} $font-family ['Material Icons'] - Font family
+/// @param {Length} $font-size [24px] - Font size
+/// @param {string} $icon ['+'] - icon to display when 'aria-expanded="false"'
+/// @param {string} $icon-expanded ['-'] - icon to display when 'aria-expanded="true"'
+/// @link https://github.com/google/material-design-icons Modified from '.material-icons' class
+/// @param {Length} $icon-offset [0] - Icon offset
+///
+/// @example - +/- toggle
+/// .plus-minus {
+/// @include mdlext-aria-expanded-toggle($font-family: inherit, $font-size: inherit);
+/// }
+/// <div aria-expanded="false">
+/// <i class="plus-minus"></i>
+/// </div>
+///
+/// @example - Material Icons, expand-more/expand_less
+/// .more-less {
+/// @include mdlext-aria-expanded-toggle($content: 'expand_more', $content-expanded: 'expand_less');
+/// }
+/// <div aria-expanded="true">
+/// <i class="more-less"></i>
+/// </div>
+
+@mixin mdlext-aria-expanded-toggle($font-family: 'Material Icons', $font-size: 24px, $icon: '+', $icon-expanded: '-', $icon-offset: 0) {
+ font-family: $font-family;
+ font-weight: inherit;
+ font-style: inherit;
+ font-size: $font-size; // Preferred icon size
+ display: inline-block;
+ width: 1em;
+ height: 1em;
+ line-height: 1;
+ text-transform: none;
+ letter-spacing: normal;
+ word-wrap: normal;
+ white-space: nowrap;
+ direction: ltr;
+ vertical-align: middle;
+
+ // Support for all WebKit browsers.
+ -webkit-font-smoothing: antialiased;
+ -webkit-font-feature-settings: 'liga';
+
+ // Support for Safari and Chrome.
+ text-rendering: optimizeLegibility;
+
+ // Support for Firefox.
+ -moz-osx-font-smoothing: grayscale;
+
+ // Support for IE.
+ font-feature-settings: 'liga';
+
+ &::after {
+ content: $icon;
+ margin-left: $icon-offset;
+ }
+
+ [aria-expanded='true'] > & {
+ &::after {
+ content: $icon-expanded;
+ margin-left: $icon-offset;
+ }
+ }
+}
+
+
+/// Keyframe mixin
+/// Modified from: http://sassbreak.com/nested-keyframe-rules-sass/
+/// Modified from: http://sassbreak.com/sass-tools-and-snippets/
+///
+/// @example
+///
+/// .some-element {
+/// animation: 10s linear infinite;
+///
+/// @include mdlext-animation-keyframes {
+/// from {
+/// background-position: 0% 0%;
+/// }
+/// to {
+/// background-position: 114.2857% 0%;
+/// }
+/// }
+/// }
+
+@mixin mdlext-animation-keyframes {
+ $animation-name: unique-id();
+ animation-name: $animation-name;
+
+ @keyframes #{$animation-name} {
+ @content;
+ }
+}
+
+
+/// Flexible title mixin
+/// A flexible title consists of three regions, left, middle and right.
+/// The left and right regions are optional and will typically contain state icons
+/// or act as a toolbar. The middle region should contain the title text.
+///
+/// @author Leif Olsen
+/// @param {String} $class - class name
+/// @gutter {Length} [8px] - horizontal spacing between title elements
+///
+/// @example
+///
+/// @include mdlext-flexible-title(my-title) {
+/// overflow: hidden;
+/// background-color: yellow;
+/// &__text {
+/// font-size: 20px;
+/// letter-spacing: 0.02em;
+/// font-weight: 400;
+/// line-height: 1.1;
+/// }
+/// }
+///
+/// <header class="my-title">
+/// <i class="material-icons" role="presentation" style="font-size: 28px;">info</i>
+/// <h2 class="my-title__text">A title</h2>
+/// <span class="my-title__spacer"></span>
+/// <i class="mdlext-aria-expanded-more-less" role="presentation" style="font-size: 28px;"></i>
+/// </header>
+
+@mixin mdlext-flexible-title($class, $gutter: 8px) {
+ .#{$class} {
+ box-sizing: border-box;
+ position: relative;
+ width: 100%;
+ display: flex;
+ align-self: stretch;
+ align-items: center;
+ margin: 0;
+ padding: 0 $gutter;
+
+ &__text,
+ &__text > * {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ > * {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0 $gutter 0 0;
+ }
+
+ > *:last-child {
+ padding-right: 0;
+ }
+
+ // Used to align elements inside a header or drawer, by growing to fill
+ // remaining space. Commonly used for aligning elements to the right.
+ &__spacer {
+ flex: 1;
+ }
+
+ @content;
+ }
+}
+
diff --git a/node_modules/mdl-ext/src/_variables.scss b/node_modules/mdl-ext/src/_variables.scss
new file mode 100644
index 0000000..908b337
--- /dev/null
+++ b/node_modules/mdl-ext/src/_variables.scss
@@ -0,0 +1,581 @@
+/**
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@import "functions";
+
+// ----------------------------------------------------------------
+// Sample colors
+// ----------------------------------------------------------------
+$mdlext-palette-amber-50: #FFF8E1;
+$mdlext-palette-amber-100: #FFECB3;
+$mdlext-palette-amber-500: #FFC107;
+$mdlext-palette-amber-700: #FFA000;
+$mdlext-palette-blue-grey-500: #607D8B;
+$mdlext-palette-deep-orange-500: #FF5722;
+$mdlext-palette-deep-purple-100: #D1C4E9;
+$mdlext-palette-deep-purple-500: #512DA8;
+$mdlext-palette-deep-purple-700: #673AB7;
+$mdlext-palette-green-50: #E8F5E9;
+$mdlext-palette-green-100: #C8E6C9;
+$mdlext-palette-green-500: #4CAF50;
+$mdlext-palette-green-700: #388E3C;
+$mdlext-palette-grey-50: #FAFAFA;
+$mdlext-palette-grey-100: #F5F5F5;
+$mdlext-palette-grey-200: #EEEEEE;
+$mdlext-palette-grey-300: #E0E0E0;
+$mdlext-palette-grey-400: #BDBDBD;
+$mdlext-palette-grey-500: #9E9E9E;
+$mdlext-palette-grey-600: #757575;
+$mdlext-palette-grey-700: #616161;
+$mdlext-palette-grey-800: #424242;
+$mdlext-palette-grey-900: #212121;
+$mdlext-palette-indigo-A200: #536DFE;
+$mdlext-palette-light-blue-500: #03A9F4;
+$mdlext-palette-light-green-500: #8BC34A;
+$mdlext-palette-pink-500: #E91E63;
+$mdlext-palette-pink-700: #C2185B;
+$mdlext-palette-pink-A400: #F50057;
+$mdlext-palette-purple-A200: #E040FB;
+$mdlext-palette-red-700: #D32F2F;
+$mdlext-palette-red-A200: #FF5252;
+$mdlext-palette-red-A400: #FF1744;
+$mdlext-palette-yellow-500: #FFEB3B;
+$mdlext-color-black: #000000;
+$mdlext-color-white: #FFFFFF;
+
+
+/* ========== Sticky Header ========== */
+$mdlext-sticky-header-background-color : transparent !default;
+$mdlext-sticky-header-background-color-scroll : transparent !default;
+$mdlext-sticky-header-gradient-color : rgb-string-to-hex($color-primary) !default;
+$mdlext-sticky-header-gradient-color-start : $mdlext-sticky-header-gradient-color !default;
+$mdlext-sticky-header-gradient-color-end : $mdlext-sticky-header-gradient-color-start !default;
+$mdlext-sticky-header-gradient-color-scroll-start: rgba($mdlext-sticky-header-gradient-color, 0.98) !default;
+$mdlext-sticky-header-gradient-color-scroll-end : rgba($mdlext-sticky-header-gradient-color, 0.95) !default;
+
+// Background shorthand
+/* stylelint-disable */
+$mdlext-sticky-header-background : $mdlext-sticky-header-background-color
+ linear-gradient(to bottom,
+ $mdlext-sticky-header-gradient-color-start 0,
+ $mdlext-sticky-header-gradient-color-end 100%) !default;
+
+// Background shorthand when content is scrolling
+$mdlext-sticky-header-background-scroll : $mdlext-sticky-header-background-color-scroll
+ linear-gradient(to bottom,
+ $mdlext-sticky-header-gradient-color-scroll-start 100%,
+ $mdlext-sticky-header-gradient-color-scroll-end 100%) !default;
+/* stylelint-enable */
+
+/* ========== Accordion ========== */
+$mdlext-accordion-header-background-color-base : $mdlext-palette-grey-500 !default;
+$mdlext-accordion-header-background-color : rgba($mdlext-accordion-header-background-color-base, 0.20) !default;
+$mdlext-accordion-header-background-open-color : rgba($mdlext-accordion-header-background-color-base, 0.30) !default;
+$mdlext-accordion-header-background-active-color : rgba($mdlext-accordion-header-background-color-base, 0.40) !default;
+$mdlext-accordion-header-border-color : rgba($mdlext-accordion-header-background-color-base, 0.50) !default;
+$mdlext-accordion-header-background-hover-color : rgba($mdlext-accordion-header-background-color-base, 0.40) !default;
+$mdlext-accordion-header-focus-outline-color : invert !default;
+$mdlext-accordion-header-disabled-color : rgba($mdlext-accordion-header-background-color-base, 0.12) !default;
+$mdlext-accordion-header-secondary-color : $mdlext-color-black !default;
+$mdlext-accordion-header-secondary-color-disabled: rgba($mdlext-color-black, 0.26) !default;
+$mdlext-accordion-header-highlight-color : darken($mdlext-accordion-header-border-color, 3%) !default;
+$mdlext-accordion-ripple-color : rgba(rgb-string-to-hex($color-accent-contrast), 0.5) !default;
+$mdlext-accordion-header-padding : 8px !default;
+$mdlext-accordion-header-height : 56px !default;
+$mdlext-accordion-content-padding : $mdlext-accordion-header-padding !default;
+$mdlext-accordion-content-color : inherit !default;
+$mdlext-accordion-content-background-color : transparent !default;
+
+
+/* ========== Dialog ========== */
+$mdlext-dialog-padding : 0;
+$mdlext-dialog-background-color : transparent !default;
+$mdlext-dialog-backdrop-color : rgba(0, 0, 0, 0.86) !default;
+$mdlext-dialog-open-animation : 0.5s 0.2s forwards !default;
+$mdlext-dialog-backdrop-animation: 0.2s forwards !default;
+
+
+/* ========== Lightbox ========== */
+$mdlext-lightbox-background-color : $card-background-color !default;
+$mdlext-lightbox-border : 0 !default;
+$mdlext-lightbox-border-radius : 0 !default;
+$mdlext-lightbox-figure-margin : 0 !default;
+$mdlext-lightbox-figure-padding : 0 !default;
+$mdlext-lightbox-figcaption-background-color: rgba(255, 255, 255, 0.76) !default;
+$mdlext-lightbox-footer-background-color : rgba(255, 255, 255, 0.86) !default;
+
+
+/* ========== Lightboard ========== */
+$mdlext-lightboard-medium-small-breakpoint : $grid-tablet-breakpoint !default; // 480
+$mdlext-lightboard-medium-breakpoint : $grid-tablet-breakpoint + 180px !default; // 480 + 180
+$mdlext-lightboard-medium-large-breakpoint : $grid-desktop-breakpoint !default; // 840
+$mdlext-lightboard-large-breakpoint : $grid-desktop-breakpoint + 360px !default; // 840+360
+
+$mdlext-lightboard-small-gutter : 2px !default;
+$mdlext-lightboard-small-margin : 0 !default;
+$mdlext-lightboard-small-columns : 2 !default;
+$mdlext-lightboard-small-frame-width : 8px !default;
+
+$mdlext-lightboard-medium-small-gutter : 4px !default;
+$mdlext-lightboard-medium-small-margin : 0 !default;
+$mdlext-lightboard-medium-small-columns : 4 !default;
+$mdlext-lightboard-medium-small-frame-width : 8px !default;
+
+$mdlext-lightboard-medium-gutter : 4px !default;
+$mdlext-lightboard-medium-margin : 0 !default;
+$mdlext-lightboard-medium-columns : 5 !default;
+$mdlext-lightboard-medium-frame-width : 8px !default;
+
+$mdlext-lightboard-medium-large-gutter : 8px !default;
+$mdlext-lightboard-medium-large-margin : 0 !default;
+$mdlext-lightboard-medium-large-columns : 6 !default;
+$mdlext-lightboard-medium-large-frame-width : 12px !default;
+
+$mdlext-lightboard-large-gutter : 8px !default;
+$mdlext-lightboard-large-margin : 0 !default;
+$mdlext-lightboard-large-columns : 7 !default;
+$mdlext-lightboard-large-frame-width : 12px !default;
+
+$mdlext-lightboard-slide-max-size : 250px !default;
+$mdlext-lightboard-slide-border-color : #D8D8D8 !default;
+$mdlext-lightboard-slide-background-color : #F8F8F8 !default;
+$mdlext-lightboard-slide-border-radius : 5px !default;
+$mdlext-lightboard-slide-inner-border-radius : 3px !default;
+$mdlext-lightboard-slide-box-shadow : 2px 2px 6px -1px rgba(219, 215, 219, 0.5) !default;
+$mdlext-lightboard-slide-border-color-hover : #B8B8B8 !default;
+$mdlext-lightboard-slide-background-color-hover: #E8E8E8 !default;
+$mdlext-lightboard-slide-active-bacground-color: #E8E8E8 !default;
+$mdlext-lightboard-slide-box-shadow-hover : 2px 2px 12px -1px rgba(219, 215, 219, 1) !default;
+$mdlext-lightboard-ripple-color : $tab-highlight-color !default;
+$mdlext-lightboard-focus-outline-color : inherit !default;
+$mdlext-lightboard-figcaption-text-color : rgb-string-to-hex($palette-grey-400) !default;
+
+
+/* ========== Carousel ========== */
+$mdlext-carousel-slide-border-top-width : 2px !default;
+$mdlext-carousel-slide-border-top-color : rgb-string-to-hex($color-accent) !default;
+$mdlext-carousel-slide-margin-horizontal : 0;
+$mdlext-carousel-slide-figcaption-color : $mdlext-lightboard-figcaption-text-color !default;
+$mdlext-carousel-slide-ripple-color : $mdlext-lightboard-ripple-color !default;
+
+
+/* ========== Bordered fields ========== */
+$mdlext-bordered-field-vertical-spacing-top : 0 !default;
+$mdlext-bordered-field-vertical-spacing-bottom : $input-text-vertical-spacing !default;
+
+$mdlext-bordered-field-input-text-font-size : $input-text-font-size !default;
+$mdlext-bordered-field-font-weight : normal !default;
+$mdlext-bordered-field-border-width : 1px !default;
+$mdlext-bordered-field-border-radius : 3px !default;
+$mdlext-bordered-field-padding : $input-text-padding + 4px !default;
+$mdlext-bordered-field-padding-top : $input-text-vertical-spacing !default;
+$mdlext-bordered-field-padding-bottom : $input-text-padding !default;
+
+$mdlext-bordered-field-input-text-color : inherit !default;
+$mdlext-bordered-field-border-color : rgba($mdlext-color-black, 0.26) !default;
+$mdlext-bordered-field-background-color : rgba(#FFFFFF, 0.2) !default;
+$mdlext-bordered-field-focus-border-color : rgb-string-to-hex($color-primary) !default;
+$mdlext-bordered-field-focus-background-color : rgba(#EEEEEE, 0.2) !default;
+
+$mdlext-bordered-field-input-text-disabled-text-color : rgba($mdlext-color-black, 0.12) !default;
+$mdlext-bordered-field-disabled-border-color : rgba($mdlext-color-black, 0.12) !default;
+$mdlext-bordered-field-disabled-background-color : $mdlext-bordered-field-background-color !default;
+
+$mdlext-bordered-field-input-text-error-color : $mdlext-bordered-field-input-text-color !default;
+$mdlext-bordered-field-error-border-color : rgb-string-to-hex($input-text-error-color) !default;
+$mdlext-bordered-field-error-background-color : rgba(lighten($mdlext-bordered-field-error-border-color, 50%), 0.5) !default;
+$mdlext-bordered-field-error-focus-border-color : darken($mdlext-bordered-field-error-border-color, 10%) !default;
+$mdlext-bordered-field-error-focus-background-color : $mdlext-bordered-field-error-background-color !default;
+
+$mdlext-bordered-field-input-text-label-color : rgba($mdlext-color-black, 0.26) !default;
+$mdlext-bordered-field-input-text-label-focus-color : $mdlext-bordered-field-focus-border-color !default;
+$mdlext-bordered-field-input-text-label-error-color : $mdlext-bordered-field-error-border-color !default;
+$mdlext-bordered-field-input-text-label-disabled-color: rgba($mdlext-color-black, 0.12) !default;
+
+$mdlext-bordered-field-label-font-size : $mdlext-bordered-field-input-text-font-size !default;
+$mdlext-bordered-field-floating-label-font-size : $input-text-floating-label-fontsize !default;
+$mdlext-bordered-field-floating-label-font-weight : normal !default;
+
+$mdlext-bordered-field-height : $mdlext-bordered-field-padding-top + $mdlext-bordered-field-padding-bottom + $mdlext-bordered-field-input-text-font-size + 6px !default;
+$mdlext-bordered-field-floating-label-focus-bottom : $mdlext-bordered-field-height - $mdlext-bordered-field-floating-label-font-size - $mdlext-bordered-field-padding-top/2 !default;
+
+
+// MDL can not handle required attribute properly. Planned for MDL-v2
+//$mdlext-bordered-field-required-border-color : rgba(rgb-string-to-hex($color-accent), 0.8) !default;
+//$mdlext-bordered-field-required-background-color : $mdlext-bordered-field-background-color !default;
+//$mdlext-bordered-field-required-focus-border-color : rgba(rgb-string-to-hex($color-accent), 0.8) !default;
+//$mdlext-bordered-field-required-focus-background-color: $mdlext-bordered-field-background-color !default;
+//$mdlext-bordered-field-label-required-color : $mdlext-bordered-field-required-border-color !default;
+
+
+
+/* ========== Color Themes ========== */
+
+// ----------------------------------------------------------------
+// Light Color Theme.
+// ----------------------------------------------------------------
+$mdlext-light-color-primary: #4CAF50 !default;
+$mdlext-light-color-primary-dark: #388E3C !default;
+$mdlext-light-color-primary-light: #4CAF50 !default; // Fallback color. Set to color-primary if fallback is not needed
+$mdlext-light-color-primary-contrast: #C8E6C9 !default; // text color on primary/primary dark background
+$mdlext-light-color-accent: #E040FB !default;
+$mdlext-light-color-accent-light: #E040FB !default; // Fallback color. Set to color-accent if fallback is not needed
+$mdlext-light-color-accent-contrast: #FAFAFA !default;
+
+$mdlext-light-content-background-color: #FAFAFA !default; // background color on content (paper/card) background
+$mdlext-light-text-color-primary: rgba($mdlext-color-black, 0.87) !default; // text color on content (paper/card) background
+$mdlext-light-text-color-secondary: rgba($mdlext-color-black, 0.54) !default; // text color on content (paper/card) background
+$mdlext-light-text-color-disabled: rgba($mdlext-color-black, 0.38) !default; // disabled text, hint text, and icons
+$mdlext-light-divider-color: rgba($mdlext-color-black, 0.12) !default; // -> $card-border-color
+$mdlext-light-error-color: #D32F2F !default;
+
+// Anchor
+$mdlext-light-text-link-color: $mdlext-light-color-accent !default;
+
+// Card
+$mdlext-light-card-background-color: $mdlext-light-content-background-color !default;
+$mdlext-light-card-text-color: $mdlext-light-text-color-primary !default;
+$mdlext-light-card-image-placeholder-color: $mdlext-light-color-accent !default;
+$mdlext-light-card-supporting-text-text-color: rgba($mdlext-color-black, 0.54) !default;
+$mdlext-light-card-border-color: rgba(0, 0, 0, 0.1) !default;
+$mdlext-light-card-subtitle-color: rgba($mdlext-color-black, 0.54) !default;
+
+// Item
+
+// Default Item Colors
+$mdlext-light-default-item-text-color: rgba($mdlext-color-black, 0.87) !default;
+$mdlext-light-default-item-outline-color: $mdlext-palette-grey-400 !default;
+$mdlext-light-default-item-hover-bg-color: $mdlext-palette-grey-200 !default;
+$mdlext-light-default-item-focus-bg-color: $mdlext-palette-grey-200 !default;
+$mdlext-light-default-item-active-bg-color: $mdlext-palette-grey-300 !default;
+$mdlext-light-default-item-divider-color: rgba($mdlext-color-black, 0.12) !default;
+
+// Disabled Button Colors
+$mdlext-light-disabled-item-text-color: $mdlext-palette-grey-400 !default;
+
+// Dropdown menu / menu-button
+$mdlext-light-default-dropdown-bg-color: $mdlext-color-white !default;
+
+// Badge
+$mdlext-light-badge-color: $mdlext-light-color-accent-contrast !default;
+$mdlext-light-badge-color-inverse: $mdlext-light-color-accent !default;
+$mdlext-light-badge-background: $mdlext-light-color-accent !default;
+$mdlext-light-badge-background-inverse: $mdlext-light-color-accent-contrast !default;
+
+// Default button colors.
+$mdlext-light-button-primary-color: rgba($mdlext-palette-grey-500, 0.20) !default;
+$mdlext-light-button-secondary-color: $mdlext-color-black !default;
+$mdlext-light-button-hover-color: $mdlext-light-button-primary-color !default;
+$mdlext-light-button-active-color: rgba($mdlext-palette-grey-500, 0.40) !default;
+$mdlext-light-button-focus-color: rgba($mdlext-color-black, 0.12) !default;
+
+// Colored button colors.
+$mdlext-light-button-primary-color-alt: $mdlext-light-color-primary-light !default;
+$mdlext-light-button-secondary-color-alt: $mdlext-light-color-primary-contrast !default;
+$mdlext-light-button-hover-color-alt: darken($mdlext-light-color-primary-light, 10%) !default;
+$mdlext-light-button-active-color-alt: darken($mdlext-light-color-primary-light, 10%) !default;
+$mdlext-light-button-focus-color-alt: $mdlext-light-button-focus-color !default;
+
+// Ripple color for colored raised buttons.
+$mdlext-light-button-ripple-color-alt: $mdlext-light-color-primary-contrast !default;
+
+// Disabled button colors.
+$mdlext-light-button-primary-color-disabled: rgba($mdlext-color-black, 0.12) !default;
+$mdlext-light-button-secondary-color-disabled: rgba($mdlext-color-black, 0.26) !default;
+
+// FAB colors and sizes.
+$mdlext-light-button-fab-color-alt: $mdlext-light-color-accent !default;
+$mdlext-light-button-fab-hover-color-alt: $mdlext-light-color-accent !default;
+$mdlext-light-button-fab-active-color-alt: $mdlext-light-color-accent !default;
+$mdlext-light-button-fab-text-color-alt: $mdlext-light-color-accent-contrast !default;
+$mdlext-light-button-fab-ripple-color-alt: $mdlext-light-color-accent-contrast !default;
+
+// Slider
+$mdlext-light-range-bg-color: rgba($mdlext-color-black, 0.26) !default;
+$mdlext-light-range-color: $mdlext-light-color-accent-light !default;
+$mdlext-light-range-faded-color: rgba($mdlext-light-color-accent-light, 0.26) !default;
+$mdlext-light-range-bg-focus-color: rgba($mdlext-color-black, 0.12) !default;
+
+// Textfields
+$mdlext-light-input-text-background-color: transparent !default;
+$mdlext-light-input-text-label-color: rgba($mdlext-color-black, 0.54) !default;
+$mdlext-light-input-text-bottom-border-color: rgba($mdlext-color-black, 0.26) !default;
+$mdlext-light-input-text-highlight-color: $mdlext-light-color-accent-light !default;
+$mdlext-light-input-text-disabled-color: rgba($mdlext-color-black, 0.12) !default;
+$mdlext-light-input-text-disabled-text-color: rgba($mdlext-color-black, 0.26) !default;
+$mdlext-light-input-text-error-color: $mdlext-light-error-color !default;
+
+// Checkboxes
+$mdlext-light-checkbox-color: $mdlext-light-color-accent-light !default;
+$mdlext-light-checkbox-off-color: rgba($mdlext-color-black, 0.54) !default;
+$mdlext-light-checkbox-disabled-color: rgba($mdlext-color-black, 0.26) !default;
+$mdlext-light-checkbox-focus-color: rgba($mdlext-light-color-accent-light, 0.26) !default;
+
+// Icon Toggles
+$mdlext-light-icon-toggle-color: $mdlext-palette-grey-700 !default;
+$mdlext-light-icon-toggle-focus-color: $mdlext-light-button-focus-color !default;
+$mdlext-light-icon-toggle-checked-color: $mdlext-light-color-accent-light !default;
+$mdlext-light-icon-toggle-checked-focus-color: rgba($mdlext-light-color-accent-light, 0.26) !default;
+$mdlext-light-icon-toggle-disabled-color: rgba($mdlext-color-black, 0.26) !default;
+
+// Radio Buttons
+$mdlext-light-radio-color: $mdlext-light-color-accent-light !default;
+$mdlext-light-radio-off-color: rgba($mdlext-color-black, 0.54) !default;
+$mdlext-light-radio-disabled-color: rgba($mdlext-color-black, 0.26) !default;
+
+// Switches
+$mdlext-light-switch-color: $mdlext-light-color-accent-light !default;
+$mdlext-light-switch-faded-color: rgba($mdlext-light-color-accent-light, 0.26) !default;
+$mdlext-light-switch-thumb-color: $mdlext-light-switch-color !default;
+$mdlext-light-switch-track-color: rgba($mdlext-light-color-accent-light, 0.54) !default;
+$mdlext-light-switch-off-thumb-color: $mdlext-palette-grey-50 !default;
+$mdlext-light-switch-off-track-color: rgba($mdlext-color-black, 0.26) !default;
+$mdlext-light-switch-disabled-thumb-color: $mdlext-palette-grey-400 !default;
+$mdlext-light-switch-disabled-track-color: rgba($mdlext-color-black, 0.12) !default;
+
+// Data table
+$mdlext-light-data-table-background-color: $mdlext-light-content-background-color !default;
+$mdlext-light-data-table-header-color: rgba($mdlext-color-black, 0.54) !default;
+$mdlext-light-data-table-header-sorted-color: rgba($mdlext-color-black, 0.87) !default;
+$mdlext-light-data-table-header-sorted-icon-hover-color: rgba($mdlext-color-black, 0.26) !default;
+$mdlext-light-data-table-hover-color: $mdlext-palette-grey-200 !default;
+$mdlext-light-data-table-selection-color: $mdlext-palette-grey-200 !default;
+$mdlext-light-data-table-divider-color: rgba($mdlext-color-black, 0.12) !default;
+$mdlext-light-data-table-dividers: 1px solid $mdlext-light-data-table-divider-color !default;
+
+
+// Selectfield
+// Uses variables from textfield
+$mdlext-selectfield-arrow-width: 0.7em;
+$mdlext-selectfield-arrow-length: 0.5em;
+
+
+// Accordion
+$mdlext-light-accordion-header-background-color-base : $mdlext-palette-grey-600 !default;
+$mdlext-light-accordion-header-background-color : rgba($mdlext-light-accordion-header-background-color-base, 0.20) !default;
+$mdlext-light-accordion-header-background-open-color : rgba($mdlext-light-accordion-header-background-color-base, 0.30) !default;
+$mdlext-light-accordion-header-background-active-color : rgba($mdlext-light-accordion-header-background-color-base, 0.40) !default;
+$mdlext-light-accordion-header-border-color : rgba($mdlext-light-accordion-header-background-color-base, 0.50) !default;
+$mdlext-light-accordion-header-background-hover-color : rgba($mdlext-light-accordion-header-background-color-base, 0.40) !default;
+$mdlext-light-accordion-header-focus-outline-color : darken($mdlext-light-accordion-header-border-color, 3%) !default;
+$mdlext-light-accordion-header-disabled-color : rgba($mdlext-light-accordion-header-background-color-base, 0.12) !default;
+$mdlext-light-accordion-header-secondary-color : $mdlext-color-black !default;
+$mdlext-light-accordion-header-secondary-color-disabled: rgba($mdlext-color-black, 0.26) !default;
+$mdlext-light-accordion-header-highlight-color : darken($mdlext-light-accordion-header-border-color, 6%) !default;
+$mdlext-light-accordion-ripple-color : rgba($mdlext-light-accordion-header-background-color-base, 0.4) !default;
+$mdlext-light-accordion-content-color : inherit !default;
+$mdlext-light-accordion-content-background-color : transparent !default;
+
+
+// Bordered fields
+$mdlext-light-bordered-field-input-text-color : inherit !default;
+$mdlext-light-bordered-field-border-color : $mdlext-light-input-text-bottom-border-color !default;
+$mdlext-light-bordered-field-background-color : rgba($mdlext-light-content-background-color, 0.1) !default;
+$mdlext-light-bordered-field-focus-border-color : $mdlext-light-color-accent-light !default;
+$mdlext-light-bordered-field-focus-background-color : rgba(darken($mdlext-light-bordered-field-background-color, 10%), 0.1) !default;
+
+$mdlext-light-bordered-field-input-text-disabled-text-color : $mdlext-light-input-text-disabled-text-color;
+$mdlext-light-bordered-field-disabled-border-color : $mdlext-light-input-text-disabled-color !default;
+$mdlext-light-bordered-field-disabled-background-color : $mdlext-light-bordered-field-background-color !default;
+
+$mdlext-light-bordered-field-input-text-error-color : $mdlext-light-bordered-field-input-text-color !default;
+$mdlext-light-bordered-field-error-border-color : $mdlext-light-input-text-error-color !default;
+$mdlext-light-bordered-field-error-background-color : rgba(lighten($mdlext-light-bordered-field-error-border-color, 50%), 0.5) !default;
+$mdlext-light-bordered-field-error-focus-border-color : darken($mdlext-light-bordered-field-error-border-color, 10%) !default;
+$mdlext-light-bordered-field-error-focus-background-color : $mdlext-light-bordered-field-error-background-color !default;
+
+$mdlext-light-bordered-field-input-text-label-color : $mdlext-light-input-text-label-color !default;
+$mdlext-light-bordered-field-input-text-label-focus-color : $mdlext-light-bordered-field-focus-border-color !default;
+$mdlext-light-bordered-field-input-text-label-error-color : $mdlext-light-bordered-field-error-border-color !default;
+$mdlext-light-bordered-field-input-text-label-disabled-color: $mdlext-light-input-text-disabled-text-color !default;
+
+
+
+// ----------------------------------------------------------------
+// Dark Color Theme.
+// ----------------------------------------------------------------
+$mdlext-dark-color-primary: #FFC107 !default;
+$mdlext-dark-color-primary-dark: #FFA000 !default;
+$mdlext-dark-color-primary-light: #FFC107 !default; // Fallback color. Set to color-primary if fallback is not needed
+$mdlext-dark-color-primary-contrast: #FFF8E1 !default; // text color on primary/primary dark background
+$mdlext-dark-color-accent: #536DFE !default;
+$mdlext-dark-color-accent-light: #536DFE !default; // Fallback color. Set to color-accent if fallback is not needed
+$mdlext-dark-color-accent-contrast: #FFFFFF !default;
+
+$mdlext-dark-content-background-color: #303030 !default; // #424242 or #303030, background color on content (paper/card) background
+$mdlext-dark-text-color-primary: rgba(#FFFFFF, 1.00) !default; // text color on content (paper/card) background
+$mdlext-dark-text-color-secondary: rgba(#FFFFFF, 0.70) !default; // text color on content (paper/card) background
+$mdlext-dark-text-color-disabled: rgba(#FFFFFF, 0.50) !default; // disabled text, hint text, and icons
+$mdlext-dark-divider-color: rgba(#FFFFFF, 0.12) !default; // -> $card-border-color
+$mdlext-dark-error-color: #FF1744 !default;
+
+// Anchor
+$mdlext-dark-text-link-color: $mdlext-dark-color-accent !default;
+
+// Card
+$mdlext-dark-card-background-color: $mdlext-dark-content-background-color !default;
+$mdlext-dark-card-text-color: $mdlext-dark-text-color-primary !default;
+$mdlext-dark-card-image-placeholder-color: $mdlext-dark-color-accent !default;
+$mdlext-dark-card-supporting-text-text-color: rgba($mdlext-color-white, 0.70) !default;
+$mdlext-dark-card-border-color: rgba(0, 0, 0, 0.1) !default;
+$mdlext-dark-card-subtitle-color: rgba($mdlext-color-black, 0.70) !default;
+
+// Item
+
+// Default Item Colors
+$mdlext-dark-default-item-text-color: rgba($mdlext-color-white, 0.87) !default;
+$mdlext-dark-default-item-outline-color: $mdlext-palette-grey-700 !default;
+$mdlext-dark-default-item-hover-bg-color: $mdlext-palette-grey-900 !default;
+$mdlext-dark-default-item-focus-bg-color: $mdlext-palette-grey-900 !default;
+$mdlext-dark-default-item-active-bg-color: $mdlext-palette-grey-800 !default;
+$mdlext-dark-default-item-divider-color: rgba($mdlext-color-white, 0.20) !default;
+
+// Disabled Button Colors
+$mdlext-dark-disabled-item-text-color: $mdlext-palette-grey-500 !default;
+
+// Dropdown menu / menu-button
+$mdlext-dark-default-dropdown-bg-color: $mdlext-color-black !default;
+
+// Badge
+$mdlext-dark-badge-color: $mdlext-dark-color-accent-contrast !default;
+$mdlext-dark-badge-color-inverse: $mdlext-dark-color-accent !default;
+$mdlext-dark-badge-background: $mdlext-dark-color-accent !default;
+$mdlext-dark-badge-background-inverse: $mdlext-dark-color-accent-contrast !default;
+
+// Default button colors.
+$mdlext-dark-button-primary-color: rgba($mdlext-palette-grey-500, 0.20) !default;
+$mdlext-dark-button-secondary-color: $mdlext-color-white !default;
+$mdlext-dark-button-hover-color: $mdlext-dark-button-primary-color !default;
+$mdlext-dark-button-active-color: rgba($mdlext-palette-grey-500, 0.40) !default;
+$mdlext-dark-button-focus-color: rgba($mdlext-color-black, 0.12) !default;
+
+// Colored button colors.
+$mdlext-dark-button-primary-color-alt: $mdlext-dark-color-primary-light !default;
+$mdlext-dark-button-secondary-color-alt: $mdlext-dark-color-primary-contrast !default;
+$mdlext-dark-button-hover-color-alt: darken($mdlext-dark-color-primary-light, 10%) !default;
+$mdlext-dark-button-active-color-alt: darken($mdlext-dark-color-primary-light, 10%) !default;
+$mdlext-dark-button-focus-color-alt: $mdlext-dark-button-focus-color !default;
+
+// Ripple color for colored raised buttons.
+$mdlext-dark-button-ripple-color-alt: $mdlext-dark-color-primary-contrast !default;
+
+// Disabled button colors.
+$mdlext-dark-button-primary-color-disabled: rgba($mdlext-color-white, 0.12) !default;
+$mdlext-dark-button-secondary-color-disabled: rgba($mdlext-color-white, 0.26) !default;
+
+// FAB colors and sizes.
+$mdlext-dark-button-fab-color-alt: $mdlext-dark-color-accent !default;
+$mdlext-dark-button-fab-hover-color-alt: $mdlext-dark-color-accent !default;
+$mdlext-dark-button-fab-active-color-alt: $mdlext-dark-color-accent !default;
+$mdlext-dark-button-fab-text-color-alt: $mdlext-dark-color-accent-contrast !default;
+$mdlext-dark-button-fab-ripple-color-alt: $mdlext-dark-color-accent-contrast !default;
+
+// Slider
+$mdlext-dark-range-bg-color: rgba($mdlext-color-white, 0.87) !default;
+$mdlext-dark-range-color: $mdlext-dark-color-accent-light !default;
+$mdlext-dark-range-faded-color: rgba($mdlext-dark-color-accent-light, 0.50) !default;
+$mdlext-dark-range-bg-focus-color: rgba($mdlext-color-white, 0.50) !default;
+
+// Textfields
+$mdlext-dark-input-text-background-color: transparent !default;
+$mdlext-dark-input-text-label-color: rgba($mdlext-color-white, 0.50) !default;
+$mdlext-dark-input-text-bottom-border-color: rgba($mdlext-color-white, 0.26) !default;
+$mdlext-dark-input-text-highlight-color: $mdlext-dark-color-accent-light !default;
+$mdlext-dark-input-text-disabled-color: rgba($mdlext-color-white, 0.12) !default;
+$mdlext-dark-input-text-disabled-text-color: rgba($mdlext-color-white, 0.26) !default;
+$mdlext-dark-input-text-error-color: $mdlext-dark-error-color !default;
+
+// Checkboxes
+$mdlext-dark-checkbox-color: $mdlext-dark-color-accent-light !default;
+$mdlext-dark-checkbox-off-color: rgba($mdlext-color-white, 0.50) !default;
+$mdlext-dark-checkbox-disabled-color: rgba($mdlext-color-white, 0.26) !default;
+$mdlext-dark-checkbox-focus-color: rgba($mdlext-dark-color-accent-light, 0.26) !default;
+
+// Icon Toggles
+$mdlext-dark-icon-toggle-color: $mdlext-palette-grey-700 !default;
+$mdlext-dark-icon-toggle-focus-color: $mdlext-dark-button-focus-color !default;
+$mdlext-dark-icon-toggle-checked-color: $mdlext-dark-color-accent-light !default;
+$mdlext-dark-icon-toggle-checked-focus-color: rgba($mdlext-dark-color-accent-light, 0.26) !default;
+$mdlext-dark-icon-toggle-disabled-color: rgba($mdlext-color-white, 0.50) !default;
+
+// Radio Buttons
+$mdlext-dark-radio-color: $mdlext-dark-color-accent-light !default;
+$mdlext-dark-radio-off-color: rgba($mdlext-color-white, 0.50) !default;
+$mdlext-dark-radio-disabled-color: rgba($mdlext-color-white, 0.26) !default;
+
+// Switches
+$mdlext-dark-switch-color: $mdlext-dark-color-accent-light !default;
+$mdlext-dark-switch-faded-color: rgba($mdlext-dark-color-accent-light, 0.26) !default;
+$mdlext-dark-switch-thumb-color: $mdlext-dark-switch-color !default;
+$mdlext-dark-switch-track-color: rgba($mdlext-dark-color-accent-light, 0.5) !default;
+$mdlext-dark-switch-off-thumb-color: $mdlext-palette-grey-50 !default;
+$mdlext-dark-switch-off-track-color: rgba($mdlext-color-white, 0.26) !default;
+$mdlext-dark-switch-disabled-thumb-color: $mdlext-palette-grey-50 !default;
+$mdlext-dark-switch-disabled-track-color: rgba($mdlext-color-white, 0.12) !default;
+
+// Data table
+$mdlext-dark-data-table-background-color: $mdlext-dark-content-background-color !default;
+$mdlext-dark-data-table-header-color: rgba($mdlext-color-white, 0.87) !default;
+$mdlext-dark-data-table-header-sorted-color: rgba($mdlext-color-white, 0.87) !default;
+$mdlext-dark-data-table-header-sorted-icon-hover-color: rgba($mdlext-color-white, 0.26) !default;
+$mdlext-dark-data-table-hover-color: $mdlext-dark-default-item-hover-bg-color !default;
+$mdlext-dark-data-table-selection-color: $mdlext-dark-default-item-active-bg-color !default;
+$mdlext-dark-data-table-divider-color: rgba($mdlext-color-white, 0.12) !default;
+$mdlext-dark-data-table-dividers: 1px solid $mdlext-dark-data-table-divider-color !default;
+
+
+// Selectfield
+// Uses variables from textfield
+
+
+// Accordion
+$mdlext-dark-accordion-header-background-color-base : $mdlext-color-black !default;
+$mdlext-dark-accordion-header-background-color : rgba($mdlext-dark-accordion-header-background-color-base, 1.0) !default;
+$mdlext-dark-accordion-header-background-open-color : rgba($mdlext-dark-accordion-header-background-color-base, 0.9) !default;
+$mdlext-dark-accordion-header-border-color : $mdlext-palette-grey-800 !default;
+$mdlext-dark-accordion-header-background-hover-color : rgba($mdlext-dark-accordion-header-background-color-base, 0.5) !default;
+$mdlext-dark-accordion-header-background-active-color : rgba($mdlext-dark-accordion-header-background-color-base, 0.6) !default;
+$mdlext-dark-accordion-header-focus-outline-color : lighten($mdlext-dark-accordion-header-border-color, 40%) !default;
+$mdlext-dark-accordion-header-disabled-color : rgba($mdlext-dark-accordion-header-background-color-base, 0.4) !default;
+$mdlext-dark-accordion-header-secondary-color : $mdlext-dark-text-color-primary !default;
+$mdlext-dark-accordion-header-secondary-color-disabled: $mdlext-dark-text-color-disabled !default;
+$mdlext-dark-accordion-header-highlight-color : lighten($mdlext-dark-accordion-header-border-color, 40%) !default;
+$mdlext-dark-accordion-ripple-color : rgba($mdlext-dark-accordion-header-background-color-base, 0.3) !default;
+$mdlext-dark-accordion-content-color : inherit !default;
+$mdlext-dark-accordion-content-background-color : transparent !default;
+
+
+// Bordered fields
+$mdlext-dark-bordered-field-input-text-color : inherit !default;
+$mdlext-dark-bordered-field-border-color : $mdlext-dark-input-text-bottom-border-color !default;
+$mdlext-dark-bordered-field-background-color : rgba($mdlext-dark-content-background-color, 0.1) !default;
+$mdlext-dark-bordered-field-focus-border-color : $mdlext-dark-color-accent-light !default;
+$mdlext-dark-bordered-field-focus-background-color : rgba(darken($mdlext-dark-bordered-field-background-color, 10%), 0.1) !default;
+
+$mdlext-dark-bordered-field-input-text-disabled-text-color : $mdlext-dark-input-text-disabled-text-color;
+$mdlext-dark-bordered-field-disabled-border-color : $mdlext-dark-input-text-disabled-color !default;
+$mdlext-dark-bordered-field-disabled-background-color : $mdlext-dark-bordered-field-background-color !default;
+
+$mdlext-dark-bordered-field-input-text-error-color : $mdlext-dark-bordered-field-input-text-color !default;
+$mdlext-dark-bordered-field-error-border-color : $mdlext-dark-input-text-error-color !default;
+$mdlext-dark-bordered-field-error-background-color : rgba($mdlext-dark-bordered-field-error-border-color, 0.1) !default;
+$mdlext-dark-bordered-field-error-focus-border-color : darken($mdlext-dark-bordered-field-error-border-color, 10%) !default;
+$mdlext-dark-bordered-field-error-focus-background-color : $mdlext-dark-bordered-field-error-background-color !default;
+
+$mdlext-dark-bordered-field-input-text-label-color : $mdlext-dark-input-text-label-color !default;
+$mdlext-dark-bordered-field-input-text-label-focus-color : $mdlext-dark-bordered-field-focus-border-color !default;
+$mdlext-dark-bordered-field-input-text-label-error-color : $mdlext-dark-bordered-field-error-border-color !default;
+$mdlext-dark-bordered-field-input-text-label-disabled-color: $mdlext-dark-input-text-disabled-text-color !default;
diff --git a/node_modules/mdl-ext/src/accordion/_accordion.scss b/node_modules/mdl-ext/src/accordion/_accordion.scss
new file mode 100644
index 0000000..6109194
--- /dev/null
+++ b/node_modules/mdl-ext/src/accordion/_accordion.scss
@@ -0,0 +1,395 @@
+@charset "UTF-8";
+
+/**
+ * @license
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+.mdlext-aria-toggle-plus-minus {
+ @include mdlext-aria-expanded-toggle($font-family: inherit, $font-size: 1.4em);
+}
+
+.mdlext-aria-toggle-material-icons {
+ @include mdlext-aria-expanded-toggle($font-size: 1.3em, $icon: 'expand_more', $icon-expanded: 'expand_less', $icon-offset: -$mdlext-accordion-header-padding);
+}
+
+.mdlext-accordion {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ display: flex;
+
+ * {
+ box-sizing: border-box;
+ }
+
+ &__panel {
+ box-sizing: border-box;
+ position: relative;
+ overflow: hidden;
+ display: flex;
+ flex-wrap: nowrap;
+ }
+
+ &__tab {
+ @include typo-title();
+
+ font-weight: 400;
+ line-height: 1.1;
+ box-sizing: border-box;
+ position: relative;
+ margin: 0;
+ padding: 0; // $mdlext-accordion-header-padding;
+ min-width: $mdlext-accordion-header-height;
+ min-height: $mdlext-accordion-header-height;
+ display: flex;
+ align-items: center;
+ align-self: stretch;
+ user-select: none;
+ color: $mdlext-accordion-header-secondary-color;
+ background-color: $mdlext-accordion-header-background-color;
+ cursor: pointer;
+ overflow: hidden;
+
+ &:focus {
+ outline-offset: -2px;
+ outline-color: $mdlext-accordion-header-focus-outline-color;
+ outline-width: 2px;
+ }
+
+ &[aria-expanded='true'] {
+ background-color: $mdlext-accordion-header-background-open-color;
+ }
+
+ &[aria-selected='true'] {
+ background-color: $mdlext-accordion-header-background-active-color;
+ }
+
+ &[disabled] {
+ background-color: $mdlext-accordion-header-disabled-color;
+ color: $mdlext-accordion-header-secondary-color-disabled;
+ pointer-events: none;
+
+ > * {
+ color: $mdlext-accordion-header-secondary-color-disabled;
+ }
+ }
+
+ &:hover:not([disabled]) {
+ background-color: $mdlext-accordion-header-background-hover-color;
+ }
+
+ > * {
+ margin: 0;
+ padding: 0;
+ }
+
+ &__caption {
+ padding-left: $mdlext-accordion-header-padding;
+ padding-right: $mdlext-accordion-header-padding;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ > *:first-child {
+ padding-left: 0;
+ }
+
+ &--ripple {
+ &[aria-selected='true']::before {
+ content: '';
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ background: $mdlext-accordion-ripple-color;
+ opacity: 0;
+ border-radius: 100%;
+ transform: scale(1, 1) translate(-50%);
+ transform-origin: 50% 50%;
+ }
+ &[aria-selected='true']:focus:not(:active)::before {
+ // http://easings.net/
+ animation: mdlext-accordion-tab-ripple 1s cubic-bezier(0.4, 0.0, 0.4, 1) 0.01s alternate forwards; // cubic-bezier(0.4, 0.0, 1, 1); //cubic-bezier(0.4, 0.0, 0.4, 1) 0.01s alternate forwards; //ease-out;
+ }
+ }
+ }
+
+ &__tabpanel {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0 $mdlext-accordion-content-padding;
+ color: $mdlext-accordion-content-color;
+ background-color: $mdlext-accordion-content-background-color;
+ display: block;
+ overflow: auto;
+ flex-grow: 1;
+
+ &[hidden] {
+ @include mdlext-visually-hidden;
+ }
+ }
+}
+
+// Vertical layout
+.mdlext-accordion {
+
+ &--vertical {
+ flex-direction: column;
+ flex-wrap: nowrap;
+
+ .mdlext-accordion__panel {
+ min-height: $mdlext-accordion-header-height;
+ flex-direction: column;
+ }
+
+ .mdlext-accordion__tab {
+ height: $mdlext-accordion-header-height;
+ border-top: 1px solid $mdlext-accordion-header-border-color;
+ padding-left: $mdlext-accordion-header-padding;
+ padding-right: $mdlext-accordion-header-padding;
+
+ &[aria-selected='true']::after {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ height: 1px;
+ width: 100%;
+ display: block;
+ content: " ";
+ background-color: $mdlext-accordion-header-highlight-color;
+ animation: border-expand 0.2s cubic-bezier(0.4, 0.0, 0.4, 1) 0.01s alternate forwards;
+ transition: all 1s cubic-bezier(0.4, 0.0, 1, 1);
+ }
+
+ > * {
+ padding-left: $mdlext-accordion-header-padding;
+ }
+
+ > *:first-child {
+ padding-left: 0;
+ }
+
+ > *:last-child:not(:only-child):not(.mdlext-accordion__tab__caption) {
+ margin-left: auto; // If more than one element, push last element to the right
+ }
+
+ &--ripple {
+ &[aria-selected='true']::before {
+ width: 5%;
+ height: 10%;
+ }
+ }
+
+ }
+
+ .mdlext-accordion__tabpanel {
+ border-top: 1px solid $mdlext-accordion-header-border-color;
+
+ &--animation {
+ transform: scaleY(1);
+ animation: mdlext-accordion-show-tabpanel-y 0.2s ease-in-out;
+
+ &[hidden] {
+ transform: scaleY(0);
+ animation: mdlext-accordion-hide-tabpanel-y 0.2s ease-out;
+ animation-delay: 0.1s;
+ }
+ }
+ }
+ }
+}
+
+// Horizontal layout
+.mdlext-accordion {
+
+ &--horizontal {
+
+ .mdlext-accordion__panel {
+ min-width: $mdlext-accordion-header-height;
+ width: $mdlext-accordion-header-height;
+ }
+
+ &[aria-multiselectable='true'] .mdlext-accordion__panel.is-expanded {
+ width: 100%;
+ }
+
+ .mdlext-accordion__tab {
+ flex-direction: column-reverse;
+ width: $mdlext-accordion-header-height;
+ white-space: nowrap;
+ border-left: 1px solid $mdlext-accordion-header-border-color;
+
+ &[aria-selected='true']::after {
+ position: absolute;
+ top: 0;
+ right: 0;
+ height: 100%;
+ width: 1px;
+ display: block;
+ content: " ";
+ background-color: $mdlext-accordion-header-highlight-color;
+
+ // Figure out how to animate a vertical line
+ //animation: border-expand 0.2s cubic-bezier(0.4, 0.0, 0.4, 1) 0.01s alternate forwards;
+ //transition: all 1s cubic-bezier(0.4, 0.0, 1, 1);
+ }
+
+ > * {
+ //transform: rotate(-90deg) translateX(50%);
+ transform: rotate(-90deg) translateX($mdlext-accordion-header-padding);
+ }
+
+ > *:last-child:not(:only-child):not(.mdlext-accordion__tab__caption) {
+ // If more than one element, push last element to top
+ margin-bottom: auto;
+ transform: rotate(-90deg) translateX(0);
+ }
+
+ &__caption {
+ transform: rotate(-90deg) translateX(50%);
+ padding-right: $mdlext-accordion-header-padding + 8px;
+ }
+
+ &--ripple {
+ &[aria-selected='true']::before {
+ width: 10%;
+ height: 5%;
+ }
+ }
+ }
+
+ .mdlext-accordion__tabpanel {
+ border-left: 1px solid $mdlext-accordion-header-border-color;
+
+ &--animation {
+ transform: scaleX(1);
+ animation: mdlext-accordion-show-tabpanel-x 0.2s ease-in-out;
+
+ &[hidden] {
+ transform: scaleX(0);
+ animation: mdlext-accordion-hide-tabpanel-x 0.2s ease-out;
+ }
+ }
+ }
+ }
+}
+
+.mdlext-accordion {
+
+ &__panel:first-child > &__tab {
+ // Use container to set outer borders
+ border-top-color: transparent;
+ border-left-color: transparent;
+ }
+
+ &[aria-multiselectable="false"] {
+ .mdlext-accordion__panel.is-expanded {
+ flex-grow: 1;
+ }
+ }
+}
+
+// Making accordion appear disabled.
+// Note: does not prevent tabbing into a disabled accordion
+.mdlext-accordion[disabled] {
+ * {
+ pointer-events: none;
+ }
+ .mdlext-accordion__tab {
+ background-color: $mdlext-accordion-header-disabled-color;
+ color: $mdlext-accordion-header-secondary-color-disabled;
+
+ > * {
+ color: $mdlext-accordion-header-secondary-color-disabled;
+ }
+ }
+ .mdlext-accordion__tabpanel {
+ opacity: 0.8;
+ filter: blur(1px) grayscale(80%);
+ }
+}
+
+
+@keyframes mdlext-accordion-tab-ripple {
+ 0% {
+ transform: scale(0, 0);
+ opacity: 1;
+ }
+ 20% {
+ transform: scale(25, 25);
+ opacity: 1;
+ }
+ 100% {
+ opacity: 0;
+ transform: scale(40, 40);
+ }
+}
+
+/*
+@keyframes mdlext-accordion-show-tabpanel-y {
+ 0% { transform: scaleY(0.1); }
+ 40% { transform: scaleY(1.03); }
+ 60% { transform: scaleY(0.98); }
+ 80% { transform: scaleY(1.03); }
+ 100% { transform: scaleY(0.98); }
+ 80% { transform: scaleY(1.01); }
+ 100% { transform: scaleY(1); }
+}
+*/
+
+@keyframes mdlext-accordion-show-tabpanel-y {
+ 0% { transform: scaleY(0); }
+ 60% { transform: scaleY(1.01); }
+ 80% { transform: scaleY(0.98); }
+ 100% { transform: scaleY(1); }
+}
+
+@keyframes mdlext-accordion-hide-tabpanel-y {
+ 0% { transform: scaleY(1); }
+ 60% { transform: scaleY(0.98); }
+ 80% { transform: scaleY(1.01); }
+ 100% { transform: scaleY(0); }
+}
+
+/*
+@keyframes mdlext-accordion-show-tabpanel-x {
+ 0% { transform: scaleX(0.1); }
+ 40% { transform: scaleX(1.03); }
+ 60% { transform: scaleX(0.98); }
+ 80% { transform: scaleX(1.03); }
+ 100% { transform: scaleX(0.98); }
+ 80% { transform: scaleX(1.01); }
+ 100% { transform: scaleX(1); }
+}
+*/
+
+@keyframes mdlext-accordion-show-tabpanel-x {
+ 0% { transform: scaleX(0); }
+ 60% { transform: scaleX(1.01); }
+ 80% { transform: scaleX(0.98); }
+ 100% { transform: scaleX(1); }
+}
+
+@keyframes mdlext-accordion-hide-tabpanel-x {
+ 0% { transform: scaleX(1); }
+ 60% { transform: scaleX(0.98); }
+ 80% { transform: scaleX(1.01); }
+ 100% { transform: scaleX(0); }
+}
diff --git a/node_modules/mdl-ext/src/accordion/accordion.js b/node_modules/mdl-ext/src/accordion/accordion.js
new file mode 100644
index 0000000..0ef7bef
--- /dev/null
+++ b/node_modules/mdl-ext/src/accordion/accordion.js
@@ -0,0 +1,549 @@
+/**
+ * @license
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+/**
+ * A WAI-ARIA friendly accordion component.
+ * An accordion is a collection of expandable panels associated with a common outer container. Panels consist
+ * of a header and an associated content region or tabpanel. The primary use of an Accordion is to present multiple sections
+ * of content on a single page without scrolling, where all of the sections are peers in the application or object hierarchy.
+ * The general look is similar to a tree where each root tree node is an expandable accordion header. The user navigates
+ * and makes the contents of each panel visible (or not) by interacting with the Accordion Header
+ */
+
+import {
+ VK_ENTER,
+ VK_SPACE,
+ VK_END,
+ VK_HOME,
+ VK_ARROW_LEFT,
+ VK_ARROW_UP,
+ VK_ARROW_RIGHT,
+ VK_ARROW_DOWN,
+ IS_EXPANDED,
+ IS_UPGRADED,
+ ARIA_MULTISELECTABLE,
+ ARIA_EXPANDED,
+ ARIA_HIDDEN,
+ ARIA_SELECTED
+} from '../utils/constants';
+
+
+(function() {
+ 'use strict';
+ const ACCORDION = 'mdlext-accordion';
+ const ACCORDION_VERTICAL = 'mdlext-accordion--vertical';
+ const ACCORDION_HORIZONTAL = 'mdlext-accordion--horizontal';
+ const PANEL = 'mdlext-accordion__panel';
+ const PANEL_ROLE = 'presentation';
+ const TAB = 'mdlext-accordion__tab';
+ const TAB_CAPTION = 'mdlext-accordion__tab__caption';
+ const TAB_ROLE = 'tab';
+ const TABPANEL = 'mdlext-accordion__tabpanel';
+ const TABPANEL_ROLE = 'tabpanel';
+ const RIPPLE_EFFECT = 'mdlext-js-ripple-effect';
+ const RIPPLE = 'mdlext-accordion__tab--ripple';
+ const ANIMATION_EFFECT = 'mdlext-js-animation-effect';
+ const ANIMATION = 'mdlext-accordion__tabpanel--animation';
+
+ /**
+ * @constructor
+ * @param {Element} element The element that will be upgraded.
+ */
+ const MaterialExtAccordion = function MaterialExtAccordion( element ) {
+
+ // Stores the Accordion HTML element.
+ this.element_ = element;
+
+ // Initialize instance.
+ this.init();
+ };
+ window['MaterialExtAccordion'] = MaterialExtAccordion;
+
+
+ // Helpers
+ const accordionPanelElements = ( element ) => {
+ if(!element) {
+ return {
+ panel: null,
+ tab: null,
+ tabpanel: null
+ };
+ }
+ else if (element.classList.contains(PANEL)) {
+ return {
+ panel: element,
+ tab: element.querySelector(`.${TAB}`),
+ tabpanel: element.querySelector(`.${TABPANEL}`)
+ };
+ }
+ else {
+ return {
+ panel: element.parentNode,
+ tab: element.parentNode.querySelector(`.${TAB}`),
+ tabpanel: element.parentNode.querySelector(`.${TABPANEL}`)
+ };
+ }
+ };
+
+
+ // Private methods.
+
+ /**
+ * Handles custom command event, 'open', 'close', 'toggle' or upgrade
+ * @param event. A custom event
+ * @private
+ */
+ MaterialExtAccordion.prototype.commandHandler_ = function( event ) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ if(event && event.detail) {
+ this.command(event.detail);
+ }
+ };
+
+ /**
+ * Dispatch toggle event
+ * @param {string} state
+ * @param {Element} tab
+ * @param {Element} tabpanel
+ * @private
+ */
+ MaterialExtAccordion.prototype.dispatchToggleEvent_ = function ( state, tab, tabpanel ) {
+ const ce = new CustomEvent('toggle', {
+ bubbles: true,
+ cancelable: true,
+ detail: { state: state, tab: tab, tabpanel: tabpanel }
+ });
+ this.element_.dispatchEvent(ce);
+ };
+
+ /**
+ * Open tab
+ * @param {Element} panel
+ * @param {Element} tab
+ * @param {Element} tabpanel
+ * @private
+ */
+ MaterialExtAccordion.prototype.openTab_ = function( panel, tab, tabpanel ) {
+ panel.classList.add(IS_EXPANDED);
+ tab.setAttribute(ARIA_EXPANDED, 'true');
+ tabpanel.removeAttribute('hidden');
+ tabpanel.setAttribute(ARIA_HIDDEN, 'false');
+ this.dispatchToggleEvent_('open', tab, tabpanel);
+ };
+
+ /**
+ * Close tab
+ * @param {Element} panel
+ * @param {Element} tab
+ * @param {Element} tabpanel
+ * @private
+ */
+ MaterialExtAccordion.prototype.closeTab_ = function( panel, tab, tabpanel ) {
+ panel.classList.remove(IS_EXPANDED);
+ tab.setAttribute(ARIA_EXPANDED, 'false');
+ tabpanel.setAttribute('hidden', '');
+ tabpanel.setAttribute(ARIA_HIDDEN, 'true');
+ this.dispatchToggleEvent_('close', tab, tabpanel);
+ };
+
+ /**
+ * Toggle tab
+ * @param {Element} panel
+ * @param {Element} tab
+ * @param {Element} tabpanel
+ * @private
+ */
+ MaterialExtAccordion.prototype.toggleTab_ = function( panel, tab, tabpanel ) {
+ if( !(this.element_.hasAttribute('disabled') || tab.hasAttribute('disabled')) ) {
+ if (tab.getAttribute(ARIA_EXPANDED).toLowerCase() === 'true') {
+ this.closeTab_(panel, tab, tabpanel);
+ }
+ else {
+ if (this.element_.getAttribute(ARIA_MULTISELECTABLE).toLowerCase() !== 'true') {
+ this.closeTabs_();
+ }
+ this.openTab_(panel, tab, tabpanel);
+ }
+ }
+ };
+
+ /**
+ * Open tabs
+ * @private
+ */
+ MaterialExtAccordion.prototype.openTabs_ = function() {
+ if (this.element_.getAttribute(ARIA_MULTISELECTABLE).toLowerCase() === 'true') {
+ [...this.element_.querySelectorAll(`.${ACCORDION} > .${PANEL}`)]
+ .filter(panel => !panel.classList.contains(IS_EXPANDED))
+ .forEach(closedItem => {
+ const tab = closedItem.querySelector(`.${TAB}`);
+ if (!tab.hasAttribute('disabled')) {
+ this.openTab_(closedItem, tab, closedItem.querySelector(`.${TABPANEL}`));
+ }
+ });
+ }
+ };
+
+ /**
+ * Close tabs
+ * @private
+ */
+ MaterialExtAccordion.prototype.closeTabs_ = function() {
+ [...this.element_.querySelectorAll(`.${ACCORDION} > .${PANEL}.${IS_EXPANDED}`)]
+ .forEach( panel => {
+ const tab = panel.querySelector(`.${TAB}`);
+ if(!tab.hasAttribute('disabled')) {
+ this.closeTab_(panel, tab, panel.querySelector(`.${TABPANEL}`));
+ }
+ });
+ };
+
+
+ // Public methods.
+
+ /**
+ * Upgrade an individual accordion tab
+ * @public
+ * @param {Element} tabElement The HTML element for the accordion panel.
+ */
+ MaterialExtAccordion.prototype.upgradeTab = function( tabElement ) {
+
+ const { panel, tab, tabpanel } = accordionPanelElements( tabElement );
+
+ const disableTab = () => {
+ panel.classList.remove(IS_EXPANDED);
+ tab.setAttribute('tabindex', '-1');
+ tab.setAttribute(ARIA_EXPANDED, 'false');
+ tabpanel.setAttribute('hidden', '');
+ tabpanel.setAttribute(ARIA_HIDDEN, 'true');
+ };
+
+ const enableTab = () => {
+ if(!tab.hasAttribute(ARIA_EXPANDED)) {
+ tab.setAttribute(ARIA_EXPANDED, 'false');
+ }
+
+ tab.setAttribute('tabindex', '0');
+
+ if(tab.getAttribute(ARIA_EXPANDED).toLowerCase() === 'true') {
+ panel.classList.add(IS_EXPANDED);
+ tabpanel.removeAttribute('hidden');
+ tabpanel.setAttribute(ARIA_HIDDEN, 'false');
+ }
+ else {
+ panel.classList.remove(IS_EXPANDED);
+ tabpanel.setAttribute('hidden', '');
+ tabpanel.setAttribute(ARIA_HIDDEN, 'true');
+ }
+ };
+
+ // In horizontal layout, caption must have a max-width defined to prevent pushing elements to the right of the caption out of view.
+ // In JsDom, offsetWidth and offsetHeight properties do not work, so this function is not testable.
+ /* istanbul ignore next */
+ const calcMaxTabCaptionWidth = () => {
+
+ const tabCaption = tab.querySelector(`.${TAB_CAPTION}`);
+ if(tabCaption !== null) {
+ const w = [...tab.children]
+ .filter( el => el.classList && !el.classList.contains(TAB_CAPTION) )
+ .reduce( (v, el) => v + el.offsetWidth, 0 );
+
+ const maxWidth = tab.clientHeight - w;
+ if(maxWidth > 0) {
+ tabCaption.style['max-width'] = `${maxWidth}px`;
+ }
+ }
+ };
+
+ const selectTab = () => {
+ if( !tab.hasAttribute(ARIA_SELECTED) ) {
+ [...this.element_.querySelectorAll(`.${TAB}[aria-selected="true"]`)].forEach(
+ selectedTab => selectedTab.removeAttribute(ARIA_SELECTED)
+ );
+ tab.setAttribute(ARIA_SELECTED, 'true');
+ }
+ };
+
+ const tabClickHandler = () => {
+ this.toggleTab_(panel, tab, tabpanel);
+ selectTab();
+ };
+
+ const tabFocusHandler = () => {
+ selectTab();
+ };
+
+ const tabpanelClickHandler = () => {
+ selectTab();
+ };
+
+ const tabpanelFocusHandler = () => {
+ selectTab();
+ };
+
+ const tabKeydownHandler = e => {
+
+ if(this.element_.hasAttribute('disabled')) {
+ return;
+ }
+
+ if ( e.keyCode === VK_END || e.keyCode === VK_HOME
+ || e.keyCode === VK_ARROW_UP || e.keyCode === VK_ARROW_LEFT
+ || e.keyCode === VK_ARROW_DOWN || e.keyCode === VK_ARROW_RIGHT ) {
+
+ let nextTab = null;
+ let keyCode = e.keyCode;
+
+ if (keyCode === VK_HOME) {
+ nextTab = this.element_.querySelector(`.${PANEL}:first-child > .${TAB}`);
+ if(nextTab && nextTab.hasAttribute('disabled')) {
+ nextTab = null;
+ keyCode = VK_ARROW_DOWN;
+ }
+ }
+ else if (keyCode === VK_END) {
+ nextTab = this.element_.querySelector(`.${PANEL}:last-child > .${TAB}`);
+ if(nextTab && nextTab.hasAttribute('disabled')) {
+ nextTab = null;
+ keyCode = VK_ARROW_UP;
+ }
+ }
+
+ if(!nextTab) {
+ let nextPanel = panel;
+
+ do {
+ if (keyCode === VK_ARROW_UP || keyCode === VK_ARROW_LEFT) {
+ nextPanel = nextPanel.previousElementSibling;
+ if(!nextPanel) {
+ nextPanel = this.element_.querySelector(`.${PANEL}:last-child`);
+ }
+ if (nextPanel) {
+ nextTab = nextPanel.querySelector(`.${PANEL} > .${TAB}`);
+ }
+ }
+ else if (keyCode === VK_ARROW_DOWN || keyCode === VK_ARROW_RIGHT) {
+ nextPanel = nextPanel.nextElementSibling;
+ if(!nextPanel) {
+ nextPanel = this.element_.querySelector(`.${PANEL}:first-child`);
+ }
+ if (nextPanel) {
+ nextTab = nextPanel.querySelector(`.${PANEL} > .${TAB}`);
+ }
+ }
+
+ if(nextTab && nextTab.hasAttribute('disabled')) {
+ nextTab = null;
+ }
+ else {
+ break;
+ }
+ }
+ while(nextPanel !== panel);
+ }
+
+ if (nextTab) {
+ e.preventDefault();
+ e.stopPropagation();
+ nextTab.focus();
+
+ // Workaround for JSDom testing:
+ // In JsDom 'element.focus()' does not trigger any focus event
+ if(!nextTab.hasAttribute(ARIA_SELECTED)) {
+
+ [...this.element_.querySelectorAll(`.${TAB}[aria-selected="true"]`)]
+ .forEach( selectedTab => selectedTab.removeAttribute(ARIA_SELECTED) );
+
+ nextTab.setAttribute(ARIA_SELECTED, 'true');
+ }
+ }
+ }
+ else if (e.keyCode === VK_ENTER || e.keyCode === VK_SPACE) {
+ e.preventDefault();
+ e.stopPropagation();
+ this.toggleTab_(panel, tab, tabpanel);
+ }
+ };
+
+ if(tab === null) {
+ throw new Error('There must be a tab element for each accordion panel.');
+ }
+
+ if(tabpanel === null) {
+ throw new Error('There must be a tabpanel element for each accordion panel.');
+ }
+
+ panel.setAttribute('role', PANEL_ROLE);
+ tab.setAttribute('role', TAB_ROLE);
+ tabpanel.setAttribute('role', TABPANEL_ROLE);
+
+ if(tab.hasAttribute('disabled')) {
+ disableTab();
+ }
+ else {
+ enableTab();
+ }
+
+ if( this.element_.classList.contains(ACCORDION_HORIZONTAL)) {
+ calcMaxTabCaptionWidth();
+ }
+
+ if (this.element_.classList.contains(RIPPLE_EFFECT)) {
+ tab.classList.add(RIPPLE);
+ }
+
+ if (this.element_.classList.contains(ANIMATION_EFFECT)) {
+ tabpanel.classList.add(ANIMATION);
+ }
+
+ // Remove listeners, just in case ...
+ tab.removeEventListener('click', tabClickHandler);
+ tab.removeEventListener('focus', tabFocusHandler);
+ tab.removeEventListener('keydown', tabKeydownHandler);
+ tabpanel.removeEventListener('click', tabpanelClickHandler);
+ tabpanel.removeEventListener('focus', tabpanelFocusHandler);
+
+ tab.addEventListener('click', tabClickHandler);
+ tab.addEventListener('focus', tabFocusHandler);
+ tab.addEventListener('keydown', tabKeydownHandler);
+ tabpanel.addEventListener('click', tabpanelClickHandler, true);
+ tabpanel.addEventListener('focus', tabpanelFocusHandler, true);
+ };
+ MaterialExtAccordion.prototype['upgradeTab'] = MaterialExtAccordion.prototype.upgradeTab;
+
+
+ /**
+ * Execute command
+ * @param detail
+ */
+ MaterialExtAccordion.prototype.command = function( detail ) {
+
+ const openTab = tabElement => {
+
+ if(tabElement === undefined) {
+ this.openTabs_();
+ }
+ else if(tabElement !== null) {
+ const { panel, tab, tabpanel } = accordionPanelElements( tabElement );
+ if(tab.getAttribute(ARIA_EXPANDED).toLowerCase() !== 'true') {
+ this.toggleTab_(panel, tab, tabpanel);
+ }
+ }
+ };
+
+ const closeTab = tabElement => {
+ if(tabElement === undefined) {
+ this.closeTabs_();
+ }
+ else if(tabElement !== null) {
+ const { panel, tab, tabpanel } = accordionPanelElements( tabElement );
+
+ if(tab.getAttribute(ARIA_EXPANDED).toLowerCase() === 'true') {
+ this.toggleTab_(panel, tab, tabpanel);
+ }
+ }
+ };
+
+ const toggleTab = tabElement => {
+ if(tabElement) {
+ const { panel, tab, tabpanel } = accordionPanelElements( tabElement );
+ this.toggleTab_(panel, tab, tabpanel);
+ }
+ };
+
+
+ if(detail && detail.action) {
+ const { action, target } = detail;
+
+ switch (action.toLowerCase()) {
+ case 'open':
+ openTab(target);
+ break;
+ case 'close':
+ closeTab(target);
+ break;
+ case 'toggle':
+ toggleTab(target);
+ break;
+ case 'upgrade':
+ if(target) {
+ this.upgradeTab(target);
+ }
+ break;
+ default:
+ throw new Error(`Unknown action "${action}". Action must be one of "open", "close", "toggle" or "upgrade"`);
+ }
+ }
+ };
+ MaterialExtAccordion.prototype['command'] = MaterialExtAccordion.prototype.command;
+
+
+ /**
+ * Initialize component
+ */
+ MaterialExtAccordion.prototype.init = function() {
+ if (this.element_) {
+ // Do the init required for this component to work
+ if( !(this.element_.classList.contains(ACCORDION_HORIZONTAL) || this.element_.classList.contains(ACCORDION_VERTICAL))) {
+ throw new Error(`Accordion must have one of the classes "${ACCORDION_HORIZONTAL}" or "${ACCORDION_VERTICAL}"`);
+ }
+
+ this.element_.setAttribute('role', 'tablist');
+
+ if(!this.element_.hasAttribute(ARIA_MULTISELECTABLE)) {
+ this.element_.setAttribute(ARIA_MULTISELECTABLE, 'false');
+ }
+
+ this.element_.removeEventListener('command', this.commandHandler_);
+ this.element_.addEventListener('command', this.commandHandler_.bind(this), false);
+
+ [...this.element_.querySelectorAll(`.${ACCORDION} > .${PANEL}`)].forEach( panel => this.upgradeTab(panel) );
+
+ // Set upgraded flag
+ this.element_.classList.add(IS_UPGRADED);
+ }
+ };
+
+
+ /*
+ * Downgrade component
+ * E.g remove listeners and clean up resources
+ *
+ * Nothing to downgrade
+ *
+ MaterialExtAccordion.prototype.mdlDowngrade_ = function() {
+ 'use strict';
+ console.log('***** MaterialExtAccordion.mdlDowngrade');
+ };
+ */
+
+
+ // The component registers itself. It can assume componentHandler is available
+ // in the global scope.
+ /* eslint no-undef: 0 */
+ componentHandler.register({
+ constructor: MaterialExtAccordion,
+ classAsString: 'MaterialExtAccordion',
+ cssClass: 'mdlext-js-accordion',
+ widget: true
+ });
+})();
diff --git a/node_modules/mdl-ext/src/accordion/readme.md b/node_modules/mdl-ext/src/accordion/readme.md
new file mode 100644
index 0000000..e8ddd3a
--- /dev/null
+++ b/node_modules/mdl-ext/src/accordion/readme.md
@@ -0,0 +1,384 @@
+# Accordion
+![Accordion](../../etc/flexbox-accordion.png)
+
+A WAI-ARIA friendly accordion component.
+
+>**Note:** The accordion has been refactored and is not compatible with accordion prior to version 0.9.13
+
+## Introduction
+An accordion component is a collection of expandable panels associated with a common outer container. Panels consist
+of a tab header and an associated content region or panel. The primary use of an Accordion is to present multiple sections
+of content on a single page without scrolling, where all of the sections are peers in the application or object hierarchy.
+The general look is similar to a tree where each root tree node is an expandable accordion header. The user navigates
+and makes the contents of each panel visible (or not) by interacting with the Accordion tab header.
+
+### Features:
+* The accordion component relates to the guidelines given in [WAI-ARIA Authoring Practices 1.1, Accordion](https://www.w3.org/TR/wai-aria-practices-1.1/#accordion)
+* User interactions via keyboard or mouse
+* Toggle a particular tab using enter or space key, or by clicking a tab
+* Client can interact with accordion using a public api og by dispatching a custom action event
+* The accordion emits a custom toggle events reflecting the tab toggled
+
+
+### To include a MDLEXT **accordion** component:
+
+ 1. Code a `<ul>` element with `class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal"` to hold the accordion with horizontal layout.
+```html
+<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal">
+</ul>
+```
+
+ 2. Code a `<li>` element with `class="mdlext-accordion__panel"` to hold an individual accordion panel.
+```html
+<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal">
+ <li class="mdlext-accordion__panel">
+ </li>
+</ul>
+```
+
+ 3. Code a `<header>` element with `class="mdlext-accordion__tab"` to hold the accordion tab header.
+```html
+<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal">
+ <li class="mdlext-accordion__panel">
+ <header class="mdlext-accordion__tab">
+ </header>
+ </li>
+</ul>
+```
+
+ 4. Code a `<span>` element with `class="mdlext-accordion__tab__caption"` to hold the accordion tab header caption.
+```html
+<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal">
+ <li class="mdlext-accordion__panel">
+ <header class="mdlext-accordion__tab">
+ <span class="mdlext-accordion__tab__caption">A tab caption</span>
+ </header>
+ </li>
+</ul>
+```
+
+ 5. Code a `<section>` element with `class="mdlext-accordion__tabpanel"` to hold the tab content.
+```html
+<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal">
+ <li class="mdlext-accordion__panel">
+ <header class="mdlext-accordion__tab">
+ <span class="mdlext-accordion__tab__caption">A tab caption</span>
+ </header>
+ <section class="mdlext-accordion__tabpanel">
+ <p>Content goes here ...</p>
+ </section>
+ </li>
+</ul>
+```
+
+ 6. Repeat steps 2..5 for each accordion panel required.
+
+### Example
+Multiselectable vertical accordion with three panels, aria attributes, ripple effect on each tab header, decorated with
+a glyph left and a state icon right. Tab #1 is open at page load (aria-expanded="true"). Subscribes to accordion toggle event.
+
+```html
+<ul id="my-accordion"
+ class="mdlext-accordion mdlext-js-accordion mdlext-accordion--vertical mdlext-js-ripple-effect"
+ role="tablist" aria-multiselectable="true">
+
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" role="tab" aria-expanded="true">
+ <i class="material-icons">dns</i>
+ <span class="mdlext-accordion__tab__caption">First section. A long caption should not push the state icon</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" aria-hidden="false">
+ <h5>Content #1 goes here</h5>
+ <p>Some content <a href="#">with an anchor</a> as a focusable element.</p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" role="tab" aria-expanded="false">
+ <i class="material-icons">all_inclusive</i>
+ <span class="mdlext-accordion__tab__caption">Tab #2</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" aria-hidden="true" hidden>
+ <h5>Content #2 goes here</h5>
+ <p>Some content....</p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" role="tab" aria-expanded="false">
+ <i class="material-icons">build</i>
+ <span class="mdlext-accordion__tab__caption">Tab #3</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" aria-hidden="true" hidden>
+ <h5>Content #3 goes here</h5>
+ </section>
+ </li>
+</ul>
+
+<script>
+ 'use strict';
+ window.addEventListener('load', function() {
+ var accordion = document.querySelector('#my-accordion');
+ accordion.addEventListener('toggle', function(e) {
+ console.log('Accordion toggled. State:', e.detail.state, 'Source:', e.detail.tab);
+ });
+ });
+</script>
+
+```
+>**Note:** All required aria attributes will be added by the accordion component during initialization - so it is not
+strictly necessary to apply the attributes in markup.
+
+### More examples
+* The [snippets/accordion.html](./snippets/accordion.html) and the [tests](../../test/accordion/accordion.spec.js) provides more detailed examples.
+* Try out the [live demo](http://leifoolsen.github.io/mdl-ext/demo/accordion.html)
+
+
+## Keyboard interaction
+The accordion interacts with the following keyboard keys.
+
+* <kbd>Tab</kbd> - When focus is on an accordion (tab)header, pressing the <kbd>Tab</kbd> key moves focus in the following manner:
+ 1. If interactive glyphs or menus are present in the accordion header, focus moves to each in order.
+ 2. When the corresponding tab panel is expanded (its [aria-expanded](http://www.w3.org/TR/wai-aria-1.1/#aria-expanded) state is 'true'), then focus moves to the first focusable element in the panel.
+ 3. If the panel is collapsed (its aria-expanded state is 'false'), OR, when the last interactive element of a panel is reached, the next <kbd>Tab</kbd> key press moves focus as follows:
+ * Moves focus to the next logical accordion header.
+ * When focus reaches the last header, focus moves to the first focusable element outside the accordion component.
+* <kbd>Left arrow</kbd>
+ * When focus is on the accordion header, a press of <kbd>up</kbd>/<kbd>left</kbd> arrow keys moves focus to the previous logical accordion header.
+ * When focus reaches the first header, further <kbd>up</kbd>/<kbd>left</kbd> arrow key presses optionally wrap to the first header.
+* <kbd>Right arrow</kbd>
+ * When focus is on the accordion header, a press of <kbd>down</kbd>/<kbd>right</kbd> arrow key moves focus to the next logical accordion header.
+ * When focus reaches the last header, further <kbd>down</kbd>/<kbd>right</kbd> arrow key presses optionally wrap to the first header
+* <kbd>Up arrow</kbd> - behaves the same as left arrow
+* <kbd>Down arrow</kbd> - behaves the same as <kbd>right arrow</kbd>
+* <kbd>End</kbd> - When focus is on the accordion header, an <kbd>End</kbd> key press moves focus to the last accordion header.
+* <kbd>Home</kbd> - When focus is on the accordion header, a <kbd>Home</kbd> key press moves focus to the first accordion header.
+* <kbd>Enter</kbd> or <kbd>Space</kbd> - When focus is on an accordion header, pressing <kbd>Enter</kbd> ir <kbd>Space</kbd> toggles the expansion of the corresponding panel.
+ * If collapsed, the panel is expanded, and its aria-expanded state is set to 'true'.
+ * If expanded, the panel is collapsed and its aria-expanded state is set to 'false'.
+* <kbd>Shift+Tab</kbd> - Generally the reverse of <kbd>Tab</kbd>.
+
+
+## Events
+Interaction with the component programmatically is performed receiving events from the component or by sending events to
+the component (or by using the public api).
+
+### Events the component listenes to
+A client can send a `command` custom event to the accordion. The command event holds a detail object defining the action
+to perform and a target for the action.
+
+The detail object has the following structure:
+```javascript
+detail: {
+ action, // "open", "close", "toggle" or "upgrade"
+ target // Target, panel or tab, of action, "undefined" if all panels should be targeted.
+ // Note: If you send a null target, the action is cancelled
+}
+```
+
+Possible actions are:
+
+#### open
+Open a targeted tab and it's corresponding tabpanel.
+
+```javascript
+myAccrdion = document.querySelector('#my-accordion');
+target = myAccordion.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(3)');
+ce = new CustomEvent('command', { detail: { action : 'open', target: target } });
+```
+If `target` is undefined, the action will open all panels.
+**Note**: Opening all panels only makes sense if the accordion has the aria attribute `aria-multiselectable` set to `true`,
+and will be cancelled otherwise.
+
+#### close
+Close a targeted tab and its corresponding tabpanel.
+
+```javascript
+myAccrdion = document.querySelector('#my-accordion');
+target = myAccordion.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(3)');
+ce = new CustomEvent('command', { detail: { action : 'close', target: target } });
+```
+If `target` is undefined, the action will close all panels.
+**Note**: Closing all panels only makes sense if the accordion has the aria attribute `aria-multiselectable` set to `true`,
+and will be cancelled otherwise.
+
+#### toggle
+Toggle a targeted tab. Open or close a targeted tab and it's corresponding tabpanel.
+
+```javascript
+myAccrdion = document.querySelector('#my-accordion');
+target = myAccordion.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(3)');
+ce = new CustomEvent('command', { detail: { action : 'toggle', target: target } });
+```
+If `target` is undefined, the action will be cancelled.
+
+#### upgrade
+Upgrade a targeted panel. If you add a panel to the accordion after the page has loaded, you must call `upgrade` to
+notify the accordion component about the new panel.
+
+```javascript
+myAccrdion = document.querySelector('#my-accordion');
+addedPanel = myAccordion.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(4)');
+ce = new CustomEvent('command', { detail: { action : 'upgrade', target: addedPanel } });
+```
+If `target` is undefined, the action will be cancelled.
+
+#### Example: Expand all panels.
+```javascript
+var ce = new CustomEvent( 'command', {
+ detail: {
+ action: 'open'
+ }
+});
+document.querySelector('#my-accordion').dispatchEvent(ce);
+```
+
+#### Example: Toggle a spesific tab.
+```javascript
+var panel3 = document.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(3) .mdlext-accordion__tab');
+var ce = new CustomEvent('command', {
+ detail: {
+ action: 'toggle',
+ target: panel3
+ }
+});
+document.querySelector('#my-accordion').dispatchEvent(ce);
+```
+
+#### Example: Append a new panel.
+```javascript
+var panel =
+ '<li class="mdlext-accordion__panel">'
+ + '<header class="mdlext-accordion__tab" aria-expanded="true">'
+ + '<span class="mdlext-accordion__tab__caption">New Tab</span>'
+ + '<i class="mdlext-aria-toggle-material-icons"></i>'
+ + '</header>'
+ + '<section class="mdlext-accordion__tabpanel">'
+ + '<h5>New tab content</h5>'
+ + '<p>Some content</p>'
+ + '</section>'
+ +'</li>';
+
+var accordion = document.querySelector('#my-accordion');
+accordion.insertAdjacentHTML('beforeend', panel);
+
+var theNewPanel = document.querySelector('#my-accordion .mdlext-accordion__panel:last-child');
+var ce = new CustomEvent('command', { detail: { action : 'upgrade', target: theNewPanel } });
+document.querySelector('#my-accordion').dispatchEvent(ce);
+```
+
+Refer to [snippets/accordion.html](./snippets/accordion.html) or the [tests](../../test/accordion/accordion.spec.js) for detailed usage.
+
+
+### Events emitted from the component
+The accordion emits a custom `toggle` event when a panel opens or closes. The event has a detail object with the following structure:
+
+```javascript
+detail: {
+ state, // "open" or "close"
+ tab, // the haeder tab element instance that caused the event
+ tabpanel // the cooresponding tabpanel element instance
+}
+```
+
+Set up an event listener to receive the toggle event.
+```javascript
+document.querySelector('#my-accordion').addEventListener('toggle', function(e) {
+ console.log('Accordion toggled. State:', e.detail.state, 'Source:', e.detail.source);
+});
+```
+Refer to [snippets/accordion.html](./snippets/accordion.html) or the [tests](../../test/accordion/accordion.spec.js) for detailed usage.
+
+
+## Public methods
+
+### upgradeTab(tabOrPanelElement)
+Upgrade a targeted panel with aria attributes and ripple effects. If you add a panel to the accordion after the page has
+loaded, you must call `upgrade` to notify the accordion component about the newly added panel.
+
+```javascript
+var accordion = document.querySelector('#my-accordion');
+var panel3 = document.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(3)');
+accordion.MaterialExtAccordion.upgradeTab( panel3 );
+```
+
+### command(detail)
+Executes an action, targeting a specific tab. The actions corresponds to the custom events defined for this component.
+
+The detail object parameter has the following structure:
+```javascript
+detail: {
+ action, // "open", "close", "toggle" or "upgrade"
+ target // Target, panel or tab, of action, "undefined" if all panels should be targeted.
+ // Note: If you send a null target, the action is cancelled
+}
+```
+
+#### open: command( {action: 'open', target: tabOrPanelElement } )
+Open a targeted tab and it's corresponding tabpanel.
+
+#### close: command( {action: 'close', target: tabOrPanelElement } )
+Close a targeted tab and it's corresponding tabpanel.
+
+#### toggle: command( {action: 'toggle', target: tabOrPanelElement } )
+Toggle a targeted tab. Open or close a targeted tab and it's corresponding tabpanel.
+
+#### upgrade: command( {action: 'upgrade', target: tabOrPanelElement } )
+Upgrade a targeted panel with aria attributes and ripple effects. If you add a panel to the accordion after the page has
+loaded, you must call `upgrade` to notify the accordion component about the newly added panel.
+
+#### Example: Expand all panels.
+```javascript
+var accordion = document.querySelector('#my-accordion');
+accordion.MaterialExtAccordion.command( {action: 'open'} );
+```
+
+#### Example: Toggle panel.
+```javascript
+var accordion = document.querySelector('#my-accordion');
+var panel3 = document.querySelector('#my-accordion .mdlext-accordion__panel:nth-child(3) .mdlext-accordion__tab');
+accordion.MaterialExtAccordion.command( {action: 'toggle', target: panel3} );
+```
+
+Refer to [snippets/accordion.html](./snippets/accordion.html) or the [tests](../../test/accordion/accordion.spec.js) for detailed usage.
+
+
+## Configuration options
+
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements to the accordion.
+The table below lists the available classes and their effects.
+
+| MDLEXT class | Effect | Remarks |
+|--------------|--------|---------|
+|`mdlext-accordion`| Defines container as an MDL component | Required on "outer" `<div>` or `<ul>` element |
+|`mdlext-js-accordion`| Assigns basic MDL behavior to accordion | Required on "outer" `<div>` or `<ul>` element |
+|`mdlext-accordion--horizontal`| Horizontal layot of an accordion | Required. The accordion must have one of `mdlext-accordion--horizontal` or `mdlext-accordion--vertical` defined |
+|`mdlext-accordion--vertical`| Vertical layot of an accordion | Required. The accordion must have one of `mdlext-accordion--horizontal` or `mdlext-accordion--vertical` defined |
+|`mdlext-js-ripple-effect`| Applies ripple click effect to accordion tab header | Optional. Goes on "outer" `<ul>` or `<div>` element |
+|`mdlext-js-animation-effect`| Applies animation effect to accordion tab panel | Optional. Goes on "outer" `<ul>` or `<div>` element |
+|`mdlext-accordion__panel`| Defines a container for each section of the accordion - the tab and tabpanel element | Required on first inner `<div>` element or `<li>` element |
+|`mdlext-accordion__tab`| Defines a tab header for a corresponding tabpanel | Required on `<header>` or `<div>` element |
+|`mdlext-accordion__tabpanel`| The content | Required on `<section>` or `<div>` element |
+
+
+The table below lists available attributes and their effects.
+
+| Attribute | Description | Remarks |
+|-----------|-------------|---------|
+|`aria-multiselectable`| If true, multiple panels may be open simultaneously | Required. Add `aria-multiselectable="true"` to the `mdlext-accordion` element to keep multiple panels open at the same time. If not present, the component will set `aria-multiselectable="false"` during initialization.|
+|`role=tablist`| Component role | Required. Added by component during initialization if not present. |
+|`role=presentation`| Accordion panel role | Required. Added by component during initialization if not present. |
+|`role=tab`| Accordion tab header role | Required. Added by component during initialization if not present. |
+|`aria-expanded`| Accordion tab header attribute. An accordion should manage the expanded/collapsed state of each tab by maintain its aria-expanded state. | Required. Defaults to `aria-expanded="false"`. Set `aria-expanded="true"` if you want a tab to open during page load. |
+|`aria-selected`| Accordion tab header attribute. An accordion should manage the selected state of each tab by maintaining its aria-selected state | Optional. Added by component. |
+|`disabled`| Accordion tab header attribute. Indicates a disabled tab and tabpanel | Optional. If this attribute is present, the tabpanel will not open or close. |
+|`role=tabpanel`| Accordion tabpanel role. | Required. Added by component during initialization if not present. |
+|`aria-hidden`| Accordion tabpanel attribute. An accordion should convey the visibility of each tabpanel by maintaining its aria-hidden state | Required. Added by component. |
+|`hidden`| Accordion tabpanel attribute. | Required. Added by component if `aria-hidden="true"`. |
+
+
+## Other examples
+* The Accordion component is based on / inspired by this [CodePen](http://codepen.io/aann/pen/dPqBML)
+* [Open Ajax, Tab Panel: Accordian1](http://www.oaa-accessibility.org/examplep/accordian1/)
+* [www3 Accordion Example](https://www.w3.org/TR/wai-aria-practices/examples/accordion/accordion1.html)
diff --git a/node_modules/mdl-ext/src/accordion/snippets/accordion.html b/node_modules/mdl-ext/src/accordion/snippets/accordion.html
new file mode 100644
index 0000000..fae785c
--- /dev/null
+++ b/node_modules/mdl-ext/src/accordion/snippets/accordion.html
@@ -0,0 +1,1072 @@
+<p>A Collection of panels within a common outer pane.</p>
+<p><strong>Note:</strong> The accordion has been refactored and is not compatible with the accordion prior to version 0.9.13</p>
+
+
+<h4>Horizontal accordion, ripple effect, animated tabpanel, aria-multiselectable="false"</h4>
+
+<style>
+ .demo-accordion-1 {
+ height: 300px; /* In horizontal layout, the accordion must have a height */
+ }
+ .demo-accordion-1 .mdlext-accordion__tabpanel {
+ background-color: rgba(239, 154, 154, 0.4); /* Just a trace color */
+ }
+</style>
+
+<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal mdlext-js-ripple-effect mdlext-js-animation-effect demo-accordion-1"
+ role="tablist" aria-multiselectable="false">
+
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="true" role="tab">
+ <i class="material-icons">info</i>
+ <span class="mdlext-accordion__tab__caption">First tab. A long caption should not push the state icon</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" aria-hidden="false">
+ <h5>Content #1 goes here</h5>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam.Fusce tincidunt leo in est <a href="#">venenatis porta</a>.
+ </p>
+ <p>Maecenas eu vestibulum orci. Ut eget nisi a est sagittis euismod a vel
+ justo. Quisque at dui urna. Duis vel velit leo. Nulla nunc sem, rutrum at aliquet in, aliquet id velit. Duis
+ mattis placerat erat, a aliquam leo rhoncus vel. Sed nec diam ex. Praesent convallis purus lorem, vel porttitor
+ neque gravida quis. Etiam et malesuada dui. Nunc vitae viverra dui. Suspendisse feugiat efficitur augue, quis
+ blandit leo ullamcorper vel.
+ </p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam.Fusce tincidunt leo in est <a href="#">venenatis porta</a>.
+ </p>
+ <p>Maecenas eu vestibulum orci. Ut eget nisi a est sagittis euismod a vel
+ justo. Quisque at dui urna. Duis vel velit leo. Nulla nunc sem, rutrum at aliquet in, aliquet id velit. Duis
+ mattis placerat erat, a aliquam leo rhoncus vel. Sed nec diam ex. Praesent convallis purus lorem, vel porttitor
+ neque gravida quis. Etiam et malesuada dui. Nunc vitae viverra dui. Suspendisse feugiat efficitur augue, quis
+ blandit leo ullamcorper vel.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <span class="mdlext-accordion__tab__caption">Tab #2</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #2 goes here</h5>
+ <p>Curabitur malesuada placerat nunc, id dapibus justo tempor in. Ut molestie
+ arcu justo, id volutpat eros vestibulum eget. Fusce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab" disabled tabindex="0">
+ <i class="material-icons">warning</i>
+ <span class="mdlext-accordion__tab__caption">Tab #3, disabled</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #3 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <i class="material-icons">accessibility</i>
+ <i class="material-icons">help_outline</i>
+ <i class="material-icons">radio</i>
+ <span class="mdlext-accordion__tab__caption">Tab #4</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #4 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">favorite</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">share</i></button>
+ <span class="mdlext-accordion__tab__caption">Tab #5, with icon buttons</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #5 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+</ul>
+
+
+
+<h4>Horizontal accordion, aria-multiselectable="true"</h4>
+<p><strong>Hint:</strong> Use a container to draw outer borders</p>
+
+<style>
+ .demo-accordion-2-container {
+ border: 1px solid #00b0ff;
+ }
+ .demo-accordion-2 {
+ height: 313px;
+ }
+ .demo-accordion-2 .mdlext-accordion__tabpanel {
+ background-color: rgba(206, 147, 216, 0.4);
+ }
+</style>
+
+<div class="demo-accordion-2-container">
+ <ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal demo-accordion-2" role="tablist" aria-multiselectable="true">
+
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="true" role="tab">
+ <i class="material-icons">info</i>
+ <span class="mdlext-accordion__tab__caption">First section. A long caption should not push the state icon</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" aria-hidden="false">
+ <h5>Content #1 goes here</h5>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam.Fusce tincidunt leo in est <a href="#">venenatis porta</a>.
+ </p>
+ <p>Maecenas eu vestibulum orci. Ut eget nisi a est sagittis euismod a vel
+ justo. Quisque at dui urna. Duis vel velit leo. Nulla nunc sem, rutrum at aliquet in, aliquet id velit. Duis
+ mattis placerat erat, a aliquam leo rhoncus vel. Sed nec diam ex. Praesent convallis purus lorem, vel porttitor
+ neque gravida quis. Etiam et malesuada dui. Nunc vitae viverra dui. Suspendisse feugiat efficitur augue, quis
+ blandit leo ullamcorper vel.
+ </p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam.Fusce tincidunt leo in est <a href="#">venenatis porta</a>.
+ </p>
+ <p>Maecenas eu vestibulum orci. Ut eget nisi a est sagittis euismod a vel
+ justo. Quisque at dui urna. Duis vel velit leo. Nulla nunc sem, rutrum at aliquet in, aliquet id velit. Duis
+ mattis placerat erat, a aliquam leo rhoncus vel. Sed nec diam ex. Praesent convallis purus lorem, vel porttitor
+ neque gravida quis. Etiam et malesuada dui. Nunc vitae viverra dui. Suspendisse feugiat efficitur augue, quis
+ blandit leo ullamcorper vel.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="true" role="tab">
+ <span class="mdlext-accordion__tab__caption">Tab #2</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #2 goes here</h5>
+ <p>Curabitur malesuada placerat nunc, id dapibus justo tempor in. Ut molestie
+ arcu justo, id volutpat eros vestibulum eget. Fusce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab" disabled tabindex="0">
+ <i class="material-icons">warning</i>
+ <span class="mdlext-accordion__tab__caption">Tab #3, disabled</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #3 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <i class="material-icons">accessibility</i>
+ <i class="material-icons">help_outline</i>
+ <i class="material-icons">radio</i>
+ <span class="mdlext-accordion__tab__caption">Tab #4, no toggle icon</span>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #4 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">favorite</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">share</i></button>
+ <span class="mdlext-accordion__tab__caption">Tab #5, with icon buttons</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #5 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ </ul>
+</div>
+
+
+
+<h4>Vertical accordion, ripple effect, animated tabpanel, aria-multiselectable="true"</h4>
+
+<style>
+ .demo-accordion-3 .mdlext-accordion__tabpanel {
+ background-color: rgba(144, 202, 249, 0.4);
+ }
+</style>
+
+<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--vertical mdlext-js-ripple-effect mdlext-js-animation-effect demo-accordion-3"
+ role="tablist" aria-multiselectable="true">
+
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="true" role="tab">
+ <i class="material-icons">info</i>
+ <span class="mdlext-accordion__tab__caption">First section. A long caption should not push the state icon</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" aria-hidden="false">
+ <h5>Content #1 goes here</h5>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam.Fusce tincidunt leo in est <a href="#">venenatis porta</a>.
+ </p>
+ <p>Maecenas eu vestibulum orci. Ut eget nisi a est sagittis euismod a vel
+ justo. Quisque at dui urna. Duis vel velit leo. Nulla nunc sem, rutrum at aliquet in, aliquet id velit. Duis
+ mattis placerat erat, a aliquam leo rhoncus vel. Sed nec diam ex. Praesent convallis purus lorem, vel porttitor
+ neque gravida quis. Etiam et malesuada dui. Nunc vitae viverra dui. Suspendisse feugiat efficitur augue, quis
+ blandit leo ullamcorper vel.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <span class="mdlext-accordion__tab__caption">Tab #2</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #2 goes here</h5>
+ <p>Curabitur malesuada placerat nunc, id dapibus justo tempor in. Ut molestie
+ arcu justo, id volutpat eros vestibulum eget. Fusce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab" disabled tabindex="0">
+ <i class="material-icons">warning</i>
+ <span class="mdlext-accordion__tab__caption">Tab #3, disabled</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #3 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <i class="material-icons">accessibility</i>
+ <i class="material-icons">help_outline</i>
+ <i class="material-icons">radio</i>
+ <span class="mdlext-accordion__tab__caption">Tab #4, no toggle icon</span>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #4 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="true" role="tab">
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">favorite</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">share</i></button>
+ <span class="mdlext-accordion__tab__caption">Tab #5, with icon buttons</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel">
+ <h5>Content #5 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+</ul>
+
+
+<h4>Vertical accordion, aria-multiselectable="false"</h4>
+<p><strong>Hint:</strong> Use a container to draw outer borders</p>
+
+<style>
+ .demo-accordion-4 {
+ height: 500px;
+ border: 1px solid #00b0ff;
+ }
+ .demo-accordion-4 .mdlext-accordion__tabpanel {
+ background-color: rgba(165, 214, 167, 0.4);
+ }
+</style>
+
+<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--vertical demo-accordion-4" role="tablist" aria-multiselectable="false">
+
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <i class="material-icons">info</i>
+ <span class="mdlext-accordion__tab__caption">First section. A long caption should not push the state icon</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel">
+ <h5>Content #1 goes here</h5>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam.Fusce tincidunt leo in est <a href="#">venenatis porta</a>.
+ </p>
+ <p>Maecenas eu vestibulum orci. Ut eget nisi a est sagittis euismod a vel
+ justo. Quisque at dui urna. Duis vel velit leo. Nulla nunc sem, rutrum at aliquet in, aliquet id velit. Duis
+ mattis placerat erat, a aliquam leo rhoncus vel. Sed nec diam ex. Praesent convallis purus lorem, vel porttitor
+ neque gravida quis. Etiam et malesuada dui. Nunc vitae viverra dui. Suspendisse feugiat efficitur augue, quis
+ blandit leo ullamcorper vel.
+ </p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam.Fusce tincidunt leo in est <a href="#">venenatis porta</a>.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="true" role="tab">
+ <span class="mdlext-accordion__tab__caption">Tab #2</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel">
+ <h5>Content #2 goes here</h5>
+ <p>Curabitur malesuada placerat nunc, id dapibus justo tempor in. Ut molestie
+ arcu justo, id volutpat eros vestibulum eget. Fusce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab" disabled>
+ <i class="material-icons">warning</i>
+ <span class="mdlext-accordion__tab__caption">Tab #3, disabled</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #3 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <i class="material-icons">accessibility</i>
+ <i class="material-icons">help_outline</i>
+ <i class="material-icons">radio</i>
+ <span class="mdlext-accordion__tab__caption">Tab #4</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel">
+ <h5>Content #4 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">favorite</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">share</i></button>
+ <span class="mdlext-accordion__tab__caption">Tab #5, with icon buttons</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel">
+ <h5>Content #5 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+</ul>
+
+
+<h4>Disabled accordion</h4>
+<ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal demo-accordion-1"
+ role="tablist" aria-multiselectable="false" disabled>
+
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="true" role="tab">
+ <i class="material-icons">info</i>
+ <span class="mdlext-accordion__tab__caption">First section. A long caption should not push the state icon</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" aria-hidden="false">
+ <h5>Content goes here</h5>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam.Fusce tincidunt leo in est <a href="#">venenatis porta</a>.
+ </p>
+ <p>Maecenas eu vestibulum orci. Ut eget nisi a est sagittis euismod a vel
+ justo. Quisque at dui urna. Duis vel velit leo. Nulla nunc sem, rutrum at aliquet in, aliquet id velit. Duis
+ mattis placerat erat, a aliquam leo rhoncus vel. Sed nec diam ex. Praesent convallis purus lorem, vel porttitor
+ neque gravida quis. Etiam et malesuada dui. Nunc vitae viverra dui. Suspendisse feugiat efficitur augue, quis
+ blandit leo ullamcorper vel.
+ </p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam.Fusce tincidunt leo in est <a href="#">venenatis porta</a>.
+ </p>
+ <p>Maecenas eu vestibulum orci. Ut eget nisi a est sagittis euismod a vel
+ justo. Quisque at dui urna. Duis vel velit leo. Nulla nunc sem, rutrum at aliquet in, aliquet id velit. Duis
+ mattis placerat erat, a aliquam leo rhoncus vel. Sed nec diam ex. Praesent convallis purus lorem, vel porttitor
+ neque gravida quis. Etiam et malesuada dui. Nunc vitae viverra dui. Suspendisse feugiat efficitur augue, quis
+ blandit leo ullamcorper vel.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <span class="mdlext-accordion__tab__caption">Tab #2</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab" disabled tabindex="0">
+ <i class="material-icons">warning</i>
+ <span class="mdlext-accordion__tab__caption">Tab #3, disabled</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <i class="material-icons">accessibility</i>
+ <i class="material-icons">help_outline</i>
+ <i class="material-icons">radio</i>
+ <span class="mdlext-accordion__tab__caption">Tab #4</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">favorite</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">share</i></button>
+ <span class="mdlext-accordion__tab__caption">Tab #5, with icon buttons</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ </section>
+ </li>
+</ul>
+
+
+
+
+<h4>Accordion API</h4>
+
+<style>
+ .cmd-button {
+ min-width: 140px;
+ }
+ .demo-accordion-6 .mdlext-accordion__tabpanel {
+ background: rgba(255, 224, 130, 0.4);
+ }
+</style>
+
+<h5>Public methods</h5>
+
+<section style="margin-bottom: 16px">
+ <button id="btn-api-expand-all" class="cmd-button mdl-button mdl-js-button mdl-button--raised">
+ Expand all
+ </button>
+ <button id="btn-api-collapse-all" class="cmd-button mdl-button mdl-js-button mdl-button--raised">
+ Collapse all
+ </button>
+ <button id="btn-api-open-tab2" class="cmd-button mdl-button mdl-js-button mdl-button--raised">
+ Open tab #2
+ </button>
+ <button id="btn-api-close-tab2" class="cmd-button mdl-button mdl-js-button mdl-button--raised">
+ Close tab #2
+ </button>
+ <button id="btn-api-toggle-tab2" class="cmd-button mdl-button mdl-js-button mdl-button--raised">
+ Toggle tab #2
+ </button>
+ <button id="btn-api-new-tab" class="cmd-button mdl-button mdl-js-button mdl-button--raised">
+ Add a new tab
+ </button>
+</section>
+
+<h5>Custom events</h5>
+
+<section style="margin-bottom: 16px">
+ <button id="btn-event-expand-all" class="cmd-button mdl-button mdl-js-button mdl-button--raised">
+ Expand all
+ </button>
+ <button id="btn-event-collapse-all" class="cmd-button mdl-button mdl-js-button mdl-button--raised">
+ Collapse all
+ </button>
+ <button id="btn-event-open-tab2" class="cmd-button mdl-button mdl-js-button mdl-button--raised">
+ Open tab #2
+ </button>
+ <button id="btn-event-close-tab2" class="cmd-button mdl-button mdl-js-button mdl-button--raised">
+ Close tab #2
+ </button>
+ <button id="btn-event-toggle-tab2" class="cmd-button mdl-button mdl-js-button mdl-button--raised">
+ Toggle tab #2
+ </button>
+ <button id="btn-event-new-tab" class="cmd-button mdl-button mdl-js-button mdl-button--raised">
+ Add a new tab
+ </button>
+</section>
+
+
+<ul id="demo-accordion-6" class="mdlext-accordion mdlext-js-accordion mdlext-accordion--vertical demo-accordion-6"
+ role="tablist" aria-multiselectable="true">
+
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="true" role="tab">
+ <i class="material-icons">info</i>
+ <span class="mdlext-accordion__tab__caption">Tab #1</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" aria-hidden="false">
+ <h5>Content #1 goes here</h5>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam.Fusce tincidunt leo in est <a href="#">venenatis porta</a>.
+ </p>
+ <p>Maecenas eu vestibulum orci. Ut eget nisi a est sagittis euismod a vel
+ justo. Quisque at dui urna. Duis vel velit leo. Nulla nunc sem, rutrum at aliquet in, aliquet id velit. Duis
+ mattis placerat erat, a aliquam leo rhoncus vel. Sed nec diam ex. Praesent convallis purus lorem, vel porttitor
+ neque gravida quis. Etiam et malesuada dui. Nunc vitae viverra dui. Suspendisse feugiat efficitur augue, quis
+ blandit leo ullamcorper vel.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <span class="mdlext-accordion__tab__caption">Tab #2</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #2 goes here</h5>
+ <p>Curabitur malesuada placerat nunc, id dapibus justo tempor in. Ut molestie
+ arcu justo, id volutpat eros vestibulum eget. Fusce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab" disabled tabindex="0">
+ <i class="material-icons">warning</i>
+ <span class="mdlext-accordion__tab__caption">Tab #3, disabled</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #3 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <i class="material-icons">accessibility</i>
+ <i class="material-icons">help_outline</i>
+ <i class="material-icons">radio</i>
+ <span class="mdlext-accordion__tab__caption">Tab #4</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #4 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">favorite</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">share</i></button>
+ <span class="mdlext-accordion__tab__caption">Tab #5, with icon buttons</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel">
+ <h5>Content #5 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+</ul>
+
+
+
+<h4>Styling the accordion</h4>
+
+<style>
+ .demo-accordion-7 {
+ height: 300px;
+ }
+ .demo-accordion-7 .mdlext-accordion__panel,
+ .demo-accordion-7 .mdlext-accordion__tab {
+ min-width: 40px;
+ min-height: 40px;
+ width: 40px;
+ }
+ .colored-panel:nth-child(1) {
+ background: rgba(239, 154, 154, 0.4);
+ }
+ .colored-panel:nth-child(2) {
+ background: rgba(206, 147, 216, 0.4);
+ }
+ .colored-panel:nth-child(3) {
+ background: rgba(144, 202, 249, 0.4);
+ }
+ .colored-panel:nth-child(4) {
+ background: rgba(165, 214, 167, 0.4);
+ }
+ .colored-panel:nth-child(5) {
+ background: rgba(255, 224, 130, 0.4);
+ }
+ .mdlext-aria-toggle-plus-minus {
+ font-size: 20px;
+ }
+ .img-box {
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+ }
+ .img-box--6 {
+ background-image: url(./images/_D806374.jpg);
+ background-image: linear-gradient(to bottom, rgba(255,255,255,0.2) 0%,rgba(255,255,255,0.2) 100%), url(./images/_D806374.jpg);
+ }
+ .img-box--7 {
+ background-image: url('./images/_D802478.jpg');
+ background-image: linear-gradient(to bottom, rgba(255,255,255,0.1) 0%,rgba(255,255,255,0.1) 100%), url(./images/_D802478.jpg);
+ }
+ .img-box--8 {
+ background-image: url('./images/_D803221.jpg');
+ background-image: linear-gradient(to bottom, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%), url(./images/_D803221.jpg);
+ }
+ .img-box--9 {
+ background-image: url('./images/_D802143-2.jpg');
+ background-image: linear-gradient(to bottom, rgba(255,255,255,0.2) 0%,rgba(255,255,255,0.2) 100%), url(./images/_D802143-2.jpg);
+ }
+ .img-box--10 {
+ background-image: url('./images/_D809758-2.jpg');
+ background-image: linear-gradient(to bottom, rgba(255,255,255,0.1) 0%,rgba(255,255,255,0.1) 100%), url(./images/_D809758-2.jpg);
+ }
+</style>
+
+<ul id="demo-accordion-7" class="mdlext-accordion mdlext-js-accordion mdlext-accordion--horizontal mdlext-js-ripple-effect mdlext-js-animation-effect demo-accordion-7">
+ <li class="mdlext-accordion__panel colored-panel">
+ <header class="mdlext-accordion__tab" aria-expanded="true">
+ <i class="material-icons md-16">dns</i>
+ <span class="mdlext-accordion__tab__caption mdl-typography--subhead-color-contrast">Accordion</span>
+ <i class="mdlext-aria-toggle-plus-minus"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel img-box img-box--6">
+ <h5>Introduction</h5>
+ <p>An accordion component is a collection of expandable panels associated with a common outer container. Panels consist
+ of a header and an associated content region or panel. The primary use of an Accordion is to present multiple sections
+ of content on a single page without scrolling, where all of the sections are peers in the application or object hierarchy.
+ The general look is similar to a tree where each root tree node is an expandable accordion header. The user navigates
+ and makes the contents of each panel visible (or not) by interacting with the Accordion Header.</p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel colored-panel">
+ <header class="mdlext-accordion__tab">
+ <i class="material-icons md-16">all_inclusive</i>
+ <span class="mdlext-accordion__tab__caption mdl-typography--subhead-color-contrast">Include Component</span>
+ <i class="mdlext-aria-toggle-plus-minus"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel img-box img-box--7">
+ <p style = "margin-top:128px;">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. Curabitur malesuada placerat nunc, id dapibus justo tempor in. Ut molestie
+ arcu justo, id volutpat eros vestibulum eget. Fusce tincidunt leo in est venenatis porta.</p>
+ <p>Maecenas eu vestibulum orci. Ut eget nisi a est sagittis euismod a vel
+ justo. Quisque at dui urna. Duis vel velit leo. Nulla nunc sem, rutrum at aliquet in, aliquet id velit. Duis
+ mattis placerat erat, a aliquam leo rhoncus vel. Sed nec diam ex. Praesent convallis purus lorem, vel porttitor
+ neque gravida quis. Etiam et malesuada dui. Nunc vitae viverra dui. Suspendisse feugiat efficitur augue, quis
+ blandit leo ullamcorper vel.</p>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. Curabitur malesuada placerat nunc, id dapibus justo tempor in. Ut molestie
+ arcu justo, id volutpat eros vestibulum eget. Fusce tincidunt leo in est venenatis porta.</p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel colored-panel">
+ <header class="mdlext-accordion__tab">
+ <i class="material-icons md-16">build</i>
+ <span class="mdlext-accordion__tab__caption mdl-typography--subhead-color-contrast">Configuration Options</span>
+ <i class="mdlext-aria-toggle-plus-minus"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel img-box img-box--8">
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. Curabitur malesuada placerat nunc, id dapibus justo tempor in. Ut molestie
+ arcu justo, id volutpat eros vestibulum eget. Fusce tincidunt leo in est venenatis porta.</p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel colored-panel">
+ <header class="mdlext-accordion__tab">
+ <i class="material-icons md-16">public</i>
+ <span class="mdlext-accordion__tab__caption mdl-typography--subhead-color-contrast">Fourth section</span>
+ <i class="mdlext-aria-toggle-plus-minus"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel img-box img-box--9">
+ <p>Maecenas eu vestibulum orci. Ut eget nisi a est sagittis euismod a vel
+ justo. Quisque at dui urna. Duis vel velit leo. Nulla nunc sem, rutrum at aliquet in, aliquet id velit. Duis
+ mattis placerat erat, a aliquam leo rhoncus vel. Sed nec diam ex. Praesent convallis purus lorem, vel porttitor
+ neque gravida quis. Etiam et malesuada dui. Nunc vitae viverra dui. Suspendisse feugiat efficitur augue, quis
+ blandit leo ullamcorper vel.</p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel colored-panel">
+ <header class="mdlext-accordion__tab">
+ <i class="material-icons md-16">public</i>
+ <span class="mdlext-accordion__tab__caption mdl-typography--subhead-color-contrast">Fifth</span>
+ <i class="mdlext-aria-toggle-plus-minus"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel img-box img-box--10">
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. Curabitur malesuada placerat nunc, id dapibus justo tempor in. Ut molestie
+ arcu justo, id volutpat eros vestibulum eget. Fusce tincidunt leo in est venenatis porta.</p>
+ </section>
+ </li>
+</ul>
+
+
+
+<h4>Color themes</h4>
+
+<div class="mdl-grid">
+ <div class="mdl-cell mdl-cell--6-col mdl-cell--4-col-tablet mdl-cell--2-col-phone mdlext-dark-color-theme">
+
+ <ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--vertical mdlext-js-ripple-effect mdlext-js-animation-effect"
+ role="tablist" aria-multiselectable="true">
+
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="true" role="tab">
+ <i class="material-icons">info</i>
+ <span class="mdlext-accordion__tab__caption">First section. A long caption should not push the state icon</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" aria-hidden="false">
+ <h5>Content #1 goes here</h5>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam.Fusce tincidunt leo in est <a href="#">venenatis porta</a>.
+ </p>
+ <p>Maecenas eu vestibulum orci. Ut eget nisi a est sagittis euismod a vel
+ justo. Quisque at dui urna. Duis vel velit leo. Nulla nunc sem, rutrum at aliquet in, aliquet id velit. Duis
+ mattis placerat erat, a aliquam leo rhoncus vel. Sed nec diam ex. Praesent convallis purus lorem, vel porttitor
+ neque gravida quis. Etiam et malesuada dui. Nunc vitae viverra dui. Suspendisse feugiat efficitur augue, quis
+ blandit leo ullamcorper vel.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <span class="mdlext-accordion__tab__caption">Tab #2</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #2 goes here</h5>
+ <p>Curabitur malesuada placerat nunc, id dapibus justo tempor in. Ut molestie
+ arcu justo, id volutpat eros vestibulum eget. Fusce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab" disabled tabindex="0">
+ <i class="material-icons">warning</i>
+ <span class="mdlext-accordion__tab__caption">Tab #3, disabled</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #3 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <i class="material-icons">accessibility</i>
+ <i class="material-icons">help_outline</i>
+ <i class="material-icons">radio</i>
+ <span class="mdlext-accordion__tab__caption">Tab #4, no toggle icon</span>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #4 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" role="tab">
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">favorite</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">share</i></button>
+ <span class="mdlext-accordion__tab__caption">Tab #5, with icon buttons</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel">
+ <h5>Content #5 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ </ul>
+ </div> <!-- mdl-cell -->
+
+ <div class="mdl-cell mdl-cell--6-col mdl-cell--4-col-tablet mdl-cell--2-col-phone">
+ <ul class="mdlext-accordion mdlext-js-accordion mdlext-accordion--vertical mdlext-js-ripple-effect mdlext-js-animation-effect mdlext-light-color-theme"
+ role="tablist" aria-multiselectable="true">
+
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="true" role="tab">
+ <i class="material-icons">info</i>
+ <span class="mdlext-accordion__tab__caption">First section. A long caption should not push the state icon</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" aria-hidden="false">
+ <h5>Content #1 goes here</h5>
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam tristique eget augue eget gravida.
+ Etiam eget imperdiet massa. Aliquam nisi eros, molestie a vulputate quis, tempor nec quam. Ut at libero
+ in sem pellentesque imperdiet. Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam.Fusce tincidunt leo in est <a href="#">venenatis porta</a>.
+ </p>
+ <p>Maecenas eu vestibulum orci. Ut eget nisi a est sagittis euismod a vel
+ justo. Quisque at dui urna. Duis vel velit leo. Nulla nunc sem, rutrum at aliquet in, aliquet id velit. Duis
+ mattis placerat erat, a aliquam leo rhoncus vel. Sed nec diam ex. Praesent convallis purus lorem, vel porttitor
+ neque gravida quis. Etiam et malesuada dui. Nunc vitae viverra dui. Suspendisse feugiat efficitur augue, quis
+ blandit leo ullamcorper vel.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <span class="mdlext-accordion__tab__caption">Tab #2</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #2 goes here</h5>
+ <p>Curabitur malesuada placerat nunc, id dapibus justo tempor in. Ut molestie
+ arcu justo, id volutpat eros vestibulum eget. Fusce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab" disabled tabindex="0">
+ <i class="material-icons">warning</i>
+ <span class="mdlext-accordion__tab__caption">Tab #3, disabled</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #3 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" aria-expanded="false" role="tab">
+ <i class="material-icons">accessibility</i>
+ <i class="material-icons">help_outline</i>
+ <i class="material-icons">radio</i>
+ <span class="mdlext-accordion__tab__caption">Tab #4, no toggle icon</span>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel" hidden aria-hidden="true">
+ <h5>Content #4 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel" role="presentation">
+ <header class="mdlext-accordion__tab" role="tab">
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">favorite</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">share</i></button>
+ <span class="mdlext-accordion__tab__caption">Tab #5, with icon buttons</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel" role="tabpanel">
+ <h5>Content #5 goes here</h5>
+ <p>Praesent pretium, sapien vel mollis porttitor, felis magna vehicula metus,
+ ac dignissim odio tortor nec quam. Nam molestie, arcu id maximus lacinia, ante ipsum posuere mauris, ac
+ maximus massa felis quis quam. usce tincidunt leo in est venenatis porta.
+ </p>
+ </section>
+ </li>
+ </ul>
+ </div> <!-- mdl-cell -->
+</div> <!-- mdl-grid -->
+
+
+
+<p class="mdl-typography--caption" style="margin-top: 64px;">
+ All images appearing in this page are the exclusive property of Leif Olsen and are protected under the United States and International Copyright laws.
+ The images may not be reproduced or manipulated without the written permission of Leif Olsen.
+ Use of any image as the basis for another photographic concept or illustration (digital, artist rendering or alike) is a violation of the United States and International Copyright laws.
+ All images are copyrighted © Leif Olsen, 2016.
+</p>
+
+<script>
+ (function() {
+ 'use strict';
+
+ function insertPanel() {
+ var panel =
+ '<li class="mdlext-accordion__panel">'
+ + '<header class="mdlext-accordion__tab" aria-expanded="true">'
+ + '<span class="mdlext-accordion__tab__caption">New Tab</span>'
+ + '<i class="mdlext-aria-toggle-material-icons"></i>'
+ + '</header>'
+ + '<section class="mdlext-accordion__tabpanel">'
+ + '<h5>New tab content</h5>'
+ + '<p>Curabitur malesuada placerat nunc, id dapibus justo tempor in. Ut molestie'
+ + 'arcu justo, id volutpat eros vestibulum eget. Fusce tincidunt leo in est venenatis porta.'
+ + '</p>'
+ + '</section>'
+ +'</li>';
+
+ var accordion = document.querySelector('#demo-accordion-6');
+ accordion.insertAdjacentHTML('beforeend', panel);
+ }
+
+ window.addEventListener('load', function() {
+
+ // Listen to accordion toggle event
+ document.querySelector('#demo-accordion-6').addEventListener('toggle', function(e) {
+ //console.log('Accordion tab toggled. New state:', e.detail.state, 'Tab:', e.detail.tab, 'Tabpanel:', e.detail.tabpanel);
+ console.log('Accordion tab toggled. New state:', e.detail.state);
+ });
+
+ // Interact with accordion using public methods
+ document.querySelector('#btn-api-expand-all').addEventListener('click', function(e) {
+ var accordion = document.querySelector('#demo-accordion-6');
+ accordion.MaterialExtAccordion.command( {action: 'open'} );
+ });
+
+ document.querySelector('#btn-api-collapse-all').addEventListener('click', function(e) {
+ var accordion = document.querySelector('#demo-accordion-6');
+ accordion.MaterialExtAccordion.command( {action: 'close'} );
+ });
+
+ document.querySelector('#btn-api-open-tab2').addEventListener('click', function(e) {
+ var accordion = document.querySelector('#demo-accordion-6');
+ var tab2 = document.querySelector('#demo-accordion-6 .mdlext-accordion__panel:nth-child(2) .mdlext-accordion__tab');
+ accordion.MaterialExtAccordion.command( {action: 'open', target: tab2} );
+ });
+
+ document.querySelector('#btn-api-close-tab2').addEventListener('click', function(e) {
+ var accordion = document.querySelector('#demo-accordion-6');
+ var tab2 = document.querySelector('#demo-accordion-6 .mdlext-accordion__panel:nth-child(2)');
+ accordion.MaterialExtAccordion.command( {action: 'close', target: tab2} );
+ });
+
+ document.querySelector('#btn-api-toggle-tab2').addEventListener('click', function(e) {
+ var accordion = document.querySelector('#demo-accordion-6');
+ var tab2 = document.querySelector('#demo-accordion-6 .mdlext-accordion__panel:nth-child(2)');
+ accordion.MaterialExtAccordion.command( {action: 'toggle', target: tab2} );
+ });
+
+ document.querySelector('#btn-api-new-tab').addEventListener('click', function(e) {
+ insertPanel();
+ var accordion = document.querySelector('#demo-accordion-6');
+ var panelElement = document.querySelector('#demo-accordion-6 .mdlext-accordion__panel:last-child');
+ accordion.MaterialExtAccordion.command( {action: 'upgrade', target: panelElement} );
+ });
+
+ // Interact with accordion using custom event
+ var eventButtons = document.querySelectorAll('button[id^="btn-event-"]');
+ for (var i = 0, n = eventButtons.length; i < n; i++) {
+ eventButtons[i].addEventListener('click', function(e) {
+ var ce;
+ var tab2 = document.querySelector('#demo-accordion-6 .mdlext-accordion__panel:nth-child(2)');
+
+ switch (e.target.id) {
+ case 'btn-event-expand-all':
+ ce = new CustomEvent('command', { detail: { action : 'open' } });
+ break;
+ case 'btn-event-collapse-all':
+ ce = new CustomEvent('command', { detail: { action : 'close' } });
+ break;
+ case 'btn-event-open-tab2':
+ ce = new CustomEvent('command', { detail: { action : 'open', target: tab2 } });
+ break;
+ case 'btn-event-close-tab2':
+ ce = new CustomEvent('command', { detail: { action : 'close', target: tab2 } });
+ break;
+ case 'btn-event-toggle-tab2':
+ ce = new CustomEvent('command', { detail: { action : 'toggle', target: tab2 } });
+ break;
+ case 'btn-event-new-tab':
+ insertPanel();
+ var panelElement = document.querySelector('#demo-accordion-6 .mdlext-accordion__panel:last-child');
+ ce = new CustomEvent('command', { detail: { action : 'upgrade', target: panelElement } });
+ break;
+ default:
+ return;
+ }
+ var accordion = document.querySelector('#demo-accordion-6');
+ accordion.dispatchEvent(ce);
+ });
+ }
+ });
+
+ }());
+
+</script>
diff --git a/node_modules/mdl-ext/src/aria-expanded-toggle/_aria-expanded-toggle.scss b/node_modules/mdl-ext/src/aria-expanded-toggle/_aria-expanded-toggle.scss
new file mode 100644
index 0000000..1f23b26
--- /dev/null
+++ b/node_modules/mdl-ext/src/aria-expanded-toggle/_aria-expanded-toggle.scss
@@ -0,0 +1,31 @@
+@charset "UTF-8";
+
+/**
+ * @license
+ * Copyright 2016-2017 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+@import "../mixins";
+
+.mdlext-aria-expanded-plus-minus {
+ @include mdlext-aria-expanded-toggle($font-family: inherit);
+}
+
+.mdlext-aria-expanded-more-less {
+ @include mdlext-aria-expanded-toggle($icon: 'expand_more', $icon-expanded: 'expand_less');
+}
diff --git a/node_modules/mdl-ext/src/bordered-fields/_bordered-fields.scss b/node_modules/mdl-ext/src/bordered-fields/_bordered-fields.scss
new file mode 100644
index 0000000..286e44a
--- /dev/null
+++ b/node_modules/mdl-ext/src/bordered-fields/_bordered-fields.scss
@@ -0,0 +1,251 @@
+/**
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The bordered fields are based on / inspired by this CodePen: http://codepen.io/prajwal078/pen/LVJZXz?editors=010
+ */
+
+// Use of this module requires the user to include variables from material-design-lite
+//@import "../../node_modules/material-design-lite/src/variables";
+//@import "../../node_modules/material-design-lite/src/mixins";
+
+@import "../variables";
+@import "../functions";
+
+
+// "Theme" for this styling
+.mdlext-bordered-fields {
+ box-sizing: border-box;
+
+ * {
+ box-sizing: border-box;
+ }
+
+ // Styling for textfield and selectfield.
+ .mdl-textfield,
+ .mdlext-selectfield {
+ padding: 0;
+ margin: $mdlext-bordered-field-vertical-spacing-top 0 $mdlext-bordered-field-vertical-spacing-bottom 0;
+
+ .mdl-textfield__input,
+ .mdlext-selectfield__select {
+ height: $mdlext-bordered-field-height;
+ background-color: $mdlext-bordered-field-background-color;
+ border: $mdlext-bordered-field-border-width solid $mdlext-bordered-field-border-color;
+ border-radius: $mdlext-bordered-field-border-radius;
+ padding: $mdlext-bordered-field-padding-top $mdlext-bordered-field-padding $mdlext-bordered-field-padding-bottom $mdlext-bordered-field-padding;
+ font-size: $mdlext-bordered-field-input-text-font-size;
+ font-weight: $mdlext-bordered-field-font-weight;
+ color: $mdlext-bordered-field-input-text-color;
+
+ &:disabled {
+ color: $mdlext-bordered-field-input-text-disabled-text-color;
+ background-color: $mdlext-bordered-field-disabled-background-color;
+ border-color: $mdlext-bordered-field-disabled-border-color;
+ }
+
+ // MDL can not handle required attribute properly. Planned for MDL-v2
+ //&:required {
+ // background-color: $mdlext-bordered-field-required-background-color;
+ // border-color: $mdlext-bordered-field-required-border-color;
+ //}
+
+ &:focus {
+ background-color: $mdlext-bordered-field-focus-background-color;
+ border-color: $mdlext-bordered-field-focus-border-color;
+ }
+
+ // MDL can not handle required. Planned for MDL-v2
+ //&:required:focus {
+ // background-color: $mdlext-bordered-field-required-focus-background-color;
+ // border-color: $mdlext-bordered-field-required-focus-border-color;
+ //}
+ }
+ .mdlext-selectfield__select {
+ padding-right: calc(1em + #{$mdlext-bordered-field-padding}); // space for down arrow
+ }
+
+ /*
+ &.is-dirty {
+ .mdl-textfield__input,
+ .mdlext-selectfield__select {
+ }
+ }
+ */
+
+ &.is-invalid {
+ .mdl-textfield__input,
+ .mdlext-selectfield__select {
+ color: $mdlext-bordered-field-input-text-error-color;
+ border-color: $mdlext-bordered-field-error-border-color;
+ background-color: $mdlext-bordered-field-error-background-color;
+
+ &:focus {
+ //&:required:focus {
+ border-color: $mdlext-bordered-field-error-focus-border-color;
+ background-color: $mdlext-bordered-field-error-focus-background-color;
+ }
+ }
+ }
+ }
+
+ .mdlext-selectfield::after {
+ top: auto;
+ bottom: $mdlext-bordered-field-padding-bottom; // Position of down arrow
+ }
+
+ fieldset[disabled] .mdlext-selectfield::after,
+ .mdlext-selectfield.is-disabled::after {
+ color: $mdlext-bordered-field-input-text-disabled-text-color;
+ @include mdlext-arrow(bottom, $mdlext-selectfield-arrow-width, $mdlext-selectfield-arrow-length, $mdlext-bordered-field-input-text-disabled-text-color);
+ }
+
+
+ fieldset[disabled] .mdl-textfield .mdl-textfield__input,
+ fieldset[disabled] .mdlext-selectfield .mdlext-selectfield__select {
+ color: $mdlext-bordered-field-input-text-disabled-text-color;
+ background-color: $mdlext-bordered-field-disabled-background-color;
+ border-color: $mdlext-bordered-field-disabled-border-color;
+ }
+
+
+ // Styling for the label / floating label.
+ .mdl-textfield,
+ .mdlext-selectfield {
+
+ &.is-dirty,
+ &.has-placeholder {
+ .mdl-textfield__label,
+ .mdlext-selectfield__label {
+ visibility: hidden;
+ }
+ }
+ .mdl-textfield__label,
+ .mdlext-selectfield__label {
+ color: $mdlext-bordered-field-input-text-label-color;
+ font-size: $mdlext-bordered-field-label-font-size;
+ font-weight: $mdlext-bordered-field-font-weight;
+ padding-left: $mdlext-bordered-field-padding;
+ top: auto;
+ bottom: $mdlext-bordered-field-padding-bottom;
+
+ // Hides the colored underline for the textField/selectfield.
+ &::after {
+ background-color: transparent !important;
+ visibility: hidden !important;
+ }
+ }
+ &.mdl-textfield--floating-label.is-focused.is-focused,
+ &.mdl-textfield--floating-label.is-dirty.is-dirty,
+ &.mdl-textfield--floating-label.has-placeholder,
+ &.mdlext-selectfield--floating-label.is-focused.is-focused,
+ &.mdlext-selectfield--floating-label.is-dirty.is-dirty,
+ &.mdlext-selectfield--floating-label.has-placeholder {
+
+ .mdl-textfield__label,
+ .mdlext-selectfield__label {
+ color: $mdlext-bordered-field-input-text-label-focus-color;
+ font-size: $mdlext-bordered-field-floating-label-font-size;
+ font-weight: $mdlext-bordered-field-floating-label-font-weight;
+ top: auto;
+ bottom: $mdlext-bordered-field-floating-label-focus-bottom;
+ visibility: visible;
+ }
+ }
+ &.mdl-textfield--floating-label.is-disabled.is-disabled,
+ &.mdlext-selectfield--floating-label.is-disabled.is-disabled {
+
+ .mdl-textfield__label,
+ .mdlext-selectfield__label {
+ color: $mdlext-bordered-field-input-text-label-disabled-color;
+ }
+ }
+ &.mdl-textfield--floating-label.is-invalid.is-invalid,
+ &.mdlext-selectfield--floating-label.is-invalid.is-invalid {
+
+ .mdl-textfield__label,
+ .mdlext-selectfield__label {
+ color: $mdlext-bordered-field-input-text-label-error-color;
+ }
+ }
+ }
+
+ fieldset[disabled] .mdl-textfield .mdl-textfield__label,
+ fieldset[disabled] .mdl-selectfield .mdl-selectfield__label {
+ color: $mdlext-bordered-field-input-text-label-disabled-color;
+ }
+
+ // Icon(s) and/or button(s) inside textfield
+ .mdl-textfield,
+ .mdlext-selectfield {
+ &.mdlext-bordered-fields__icon-left,
+ &.mdlext-bordered-fields__icon-right {
+ & > i,
+ & > .mdl-button {
+ position: absolute;
+ bottom: $mdlext-bordered-field-padding-bottom - 2px;
+ }
+ & > i {
+ bottom: $mdlext-bordered-field-padding-bottom + 2px;
+ }
+ }
+ &.mdlext-bordered-fields__icon-left {
+ & > i:first-child,
+ & > .mdl-button:first-child {
+ left: $mdlext-bordered-field-padding/2;
+ }
+ & > i ~ .mdl-textfield__input,
+ & > .mdl-button ~ .mdl-textfield__input,
+ & > i ~ .mdlext-selectfield__select,
+ & > .mdl-button ~ .mdlext-selectfield__select {
+ padding-left: $input-text-button-size;
+ }
+ & > i ~ .mdl-textfield__label,
+ & > .mdl-button ~ .mdl-textfield__label {
+ left: $input-text-button-size - $mdlext-bordered-field-padding;
+ }
+ & > i ~ .mdlext-selectfield__label,
+ & > .mdl-button ~ .mdlext-selectfield__label {
+ left: $input-text-button-size - $mdlext-bordered-field-padding;
+ }
+ }
+ &.mdlext-bordered-fields__icon-right {
+ & > .mdl-textfield__input {
+ padding-right: $input-text-button-size;
+ }
+ & > i:last-child,
+ & > .mdl-button:last-child {
+ left: auto;
+ right: $mdlext-bordered-field-padding/2;
+ }
+ }
+ &.is-disabled i,
+ &.is-disabled .mdl-button {
+ color: $mdlext-bordered-field-disabled-border-color;
+ pointer-events: none;
+ }
+ }
+
+ fieldset[disabled] .mdl-textfield,
+ fieldset[disabled] .mdlext-selectfield {
+ i,
+ .mdl-button {
+ color: $mdlext-bordered-field-disabled-border-color;
+ pointer-events: none;
+ }
+ }
+}
+
diff --git a/node_modules/mdl-ext/src/bordered-fields/readme.md b/node_modules/mdl-ext/src/bordered-fields/readme.md
new file mode 100644
index 0000000..40dcfff
--- /dev/null
+++ b/node_modules/mdl-ext/src/bordered-fields/readme.md
@@ -0,0 +1,98 @@
+# Bordered fields
+![Bordered fields](../../etc/bordered-fields-theme.png)
+
+Demonstrates how you can create your own theme of MDL text fields.
+
+## Introduction
+The Material Design Lite Ext (MDLEXT) bordered fields component is a method for decorating contained
+MDL textfields and MDLEXT selectfields without affecting the original MDL design. You can apply the `mdlext-bordered-fields` class
+to any HTML block element and use that as a container for the bordered fields.
+
+### To include a MDLEXT **bordered fields** component:
+ 1. Code a block element, as the "outer" container, intended to hold all of the bordered fields.
+```html
+<div>
+</div>
+```
+
+ 2. Add the `mdlext-bordered-fields` MDLEXT class to the block element using the `class` attribute.
+```html
+<div class="mdlext-bordered-fields">
+</div>
+```
+
+ 3. Add the MDL and MDLEXT fields you want to decorate.
+```html
+<div class="mdlext-bordered-fields">
+ <div class="mdl-textfield mdl-js-textfield">
+ <input class="mdl-textfield__input" type="text" id="sample1">
+ <label class="mdl-textfield__label" for="sample1">Text ...</label>
+ </div>
+
+ <div class="mdlext-selectfield mdlext-js-selectfield">
+ <select class="mdlext-selectfield__select" id="nordic-countries" name="nordic-countries">
+ <option value=""></option>
+ <option value="option1">Norway</option>
+ <option value="option2">Sweden</option>
+ <option value="option3">Suomi</option>
+ <option value="option4">Denmark</option>
+ <option value="option5">Iceland</option>
+ </select>
+ <label class="mdlext-selectfield__label" for="nordic-countries">Where do you want to go</label>
+ </div>
+ .....
+</div>
+```
+
+ 4. Optionally embed icons and/or buttons into a bordered field by adding the CSS classes
+`mdlext-bordered-fields__icon-left` and `mdlext-bordered-fields__icon-right` respectively.
+```html
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text" id="icon-button1">
+ <label class="mdl-textfield__label">Text...</label>
+ <label class="mdl-button mdl-js-button mdl-button--icon" for="icon-button1">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-bordered-fields__icon-left">
+ <i class="material-icons">radio</i>
+ <select class="mdlext-selectfield__select" id="nordic-countries" name="nordic-countries">
+ <option value=""></option>
+ <option value="option1">Norway</option>
+ <option value="option2">Sweden</option>
+ <option value="option3">Suomi</option>
+ <option value="option4">Denmark</option>
+ <option value="option5">Iceland</option>
+ </select>
+ <label class="mdlext-selectfield__label" for="nordic-countries">Where do you want to go</label>
+ </div>
+```
+
+>**Note:** The `mdlext-selectfield` component can only embed an icon at the left hand side.
+
+#### Examples
+See the [example code](./snippets/bordered-fields.html).
+
+## Configuration options
+
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements to text fields and select fields.
+The table below lists the available classes and their effects.
+
+| MDLEXT class | Effect | Remarks |
+|-----------|--------|---------|
+| `mdlext-bordered-fields` | Defines container as an MDL bordered fields component | Required on an "outer" block element|
+| `mdlext-bordered-fields__icon-left` | Add class on `mdl-textfield` or `mdlext-selectfield` container if you want to embedd a left aligned icon or a button into the bordered field | |
+| `mdlext-bordered-fields__icon-right` | Add class on `mdl-textfield` or `mdlext-selectfield` container if you want to embedd a right aligned icon or a button into the bordered field | |
+
+
+### SASS variables.
+
+See: [variables.scss](../_variables.scss)
+
+### Calculations of heights, vertical spacing and positioning of labels and icons
+See: [bordered-fields.scss](./_bordered-fields.scss)
+
+### Credits
+The Bordered Fields component is based on this [CodePen](http://codepen.io/prajwal078/pen/LVJZXz)
diff --git a/node_modules/mdl-ext/src/bordered-fields/snippets/bordered-fields.html b/node_modules/mdl-ext/src/bordered-fields/snippets/bordered-fields.html
new file mode 100644
index 0000000..5b14918
--- /dev/null
+++ b/node_modules/mdl-ext/src/bordered-fields/snippets/bordered-fields.html
@@ -0,0 +1,376 @@
+<p>Demonstrates how you can create your own theme of MDL text fields without affecting the original MDL fields.</p>
+
+<style>
+ .borderedfield-demo-container {
+ }
+
+ .borderedfield-demo-container .mdl-cell {
+ padding: 0 4px 8px 0;
+ }
+
+ .borderedfield-demo-container .mdl-cell p {
+ margin-bottom: 0;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+
+ /* File input example */
+ .mdl-button--file input {
+ cursor: pointer;
+ opacity: 0;
+ width: 1px;
+ height: 1px;
+ }
+</style>
+
+
+<div class = "borderedfield-demo-container mdlext-bordered-fields">
+
+ <div class="mdl-grid mdl-grid--no-spacing">
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Text</p>
+ <div class="mdl-textfield mdl-js-textfield">
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Text numeric</p>
+ <div class="mdl-textfield mdl-js-textfield">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Text with floating label, required field</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" list="languages" placeholder="Select a language" required>
+ <label class="mdl-textfield__label">Programming language</label>
+ </div>
+ </div>
+ <datalist id="languages">
+ <option value="HTML">
+ <option value="CSS">
+ <option value="JavaScript">
+ <option value="Java">
+ <option value="Ruby">
+ <option value="PHP">
+ <option value="Go">
+ <option value="Erlang">
+ <option value="Python">
+ <option value="C">
+ <option value="C#">
+ <option value="C++">
+ </datalist>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Select element with floating label</p>
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ <option value="option6">option 5 abcdefghijklmnopqrstuvw0123456789</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Numeric with floating label</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Disabled floating label</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?" disabled value="123">
+ <label class="mdl-textfield__label" >Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Text with icons left and right, disabled</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text" disabled>
+ <label class="mdl-textfield__label">Text...</label>
+ <i class="material-icons">fingerprint</i>
+ </div>
+ </div>
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Text with button left</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Text with button right</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right">
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Select element</p>
+ <div class="mdlext-selectfield mdlext-js-selectfield">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ <option value="option6">option 5 abcdefghijklmnopqrstuvw0123456789</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Select element with floating label</p>
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Disabled Select element</p>
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select" disabled>
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Select element with icon left</p>
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-bordered-fields__icon-left">
+ <i class="material-icons">radio</i>
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Select element with button left</p>
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label mdlext-bordered-fields__icon-left">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Disabled Select element</p>
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label mdlext-bordered-fields__icon-left">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+ <select class="mdlext-selectfield__select" disabled>
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Text with icon left</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Text with icon right</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right">
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <i class="material-icons">fingerprint</i>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Text with icons left and right</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <i class="material-icons">fingerprint</i>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Text with buttons left and right</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Text with buttons left and right, disabled</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+
+ <input class="mdl-textfield__input" type="text" disabled>
+ <label class="mdl-textfield__label">Text...</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>Text with icon and button</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>File upload</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right ">
+ <input class="mdl-textfield__input" type="text" id="uploadfile2" readonly>
+ <label class="mdl-textfield__label">File (work in progress)</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--primary mdl-button--icon mdl-button--file" for="uploadfile2">
+ <i class="material-icons">attach_file</i>
+ <input type="file" id="uploadBtn2">
+ </label>
+ </div>
+ <!--
+ // Need a script to work properly - something like this
+ -->
+ <script>
+ (function() {
+ 'use strict';
+ document.querySelector('#uploadBtn2').addEventListener('change', function() {
+ var n = document.querySelector("#uploadfile2");
+ n.value = this.files[0].name;
+ n.parentNode.classList.add('is-dirty');
+ });
+ }());
+ </script>
+ </div>
+
+ </div>
+
+ <fieldset disabled>
+ <legend>Disabled fieldset</legend>
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ <option value="option6">option 5 abcdefghijklmnopqrstuvw0123456789</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </fieldset>
+
+</div>
+
+<h5>Credits</h5>
+<p>The Bordered Fields Theme component is based on this <a href="http://codepen.io/prajwal078/pen/LVJZXz" target="_blank">CodePen</a></p>
diff --git a/node_modules/mdl-ext/src/carousel/_carousel.scss b/node_modules/mdl-ext/src/carousel/_carousel.scss
new file mode 100644
index 0000000..674751a
--- /dev/null
+++ b/node_modules/mdl-ext/src/carousel/_carousel.scss
@@ -0,0 +1,141 @@
+@charset "UTF-8";
+
+/**
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * A carousel ...
+ */
+
+// Use of this module requires the user to include variables from material-design-lite
+//@import "../../node_modules/material-design-lite/src/variables";
+//@import "../../node_modules/material-design-lite/src/mixins";
+
+ul.mdlext-carousel {
+ list-style: none;
+}
+
+.mdlext-carousel {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ overflow: hidden;
+ height: 100%; // Use a container to constrain height and width
+ width: 100%;
+ display: block;
+ white-space: nowrap;
+ font-size: 0;
+ background-color: transparent;
+}
+
+.mdlext-carousel__slide {
+ box-sizing: border-box;
+ display: inline-block;
+ position: relative;
+ outline: 0;
+ margin: 0 $mdlext-carousel-slide-margin-horizontal;
+ padding:0;
+ height: 100%;
+ border-top: $mdlext-carousel-slide-border-top-width solid transparent; // Makes room for the animated select/focus line
+
+ //&:focus,
+ &[aria-selected],
+ &[aria-selected='true'] {
+ figcaption {
+ // As far as I can see there is no way to darken/lighten a text color
+ // defined by MDL, due to the "unqote" functions.
+ // So this is a hack
+ color: rgba(0, 0, 0, 1) !important;
+ background-color: rgba(255, 255, 255, 0.25);
+ }
+ }
+
+ &[aria-selected]::after,
+ &[aria-selected='true']::after {
+ height: $mdlext-carousel-slide-border-top-width;
+ width: 100%;
+ display: block;
+ content: ' ';
+ top: (-$mdlext-carousel-slide-border-top-width);
+ left: 0;
+ position: absolute;
+ background: $mdlext-carousel-slide-border-top-color;
+ animation: border-expand 0.2s cubic-bezier(0.4, 0.0, 0.4, 1) 0.01s alternate forwards;
+ transition: all 1s cubic-bezier(0.4, 0.0, 1, 1);
+ }
+
+
+ a {
+ text-decoration: none;
+ }
+
+ figure {
+ box-sizing: border-box;
+ position: relative;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+
+ img {
+ box-sizing: border-box;
+ max-height: 100%;
+ }
+
+ figcaption {
+ box-sizing: border-box;
+ @include typo-caption($colorContrast: false, $usePreferred: true);
+
+ color: $mdlext-carousel-slide-figcaption-color;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ white-space: nowrap;
+ overflow: hidden;
+ max-width: 100%;
+ width: 100%;
+ text-align: center;
+ text-overflow: ellipsis;
+ padding: 4px 0;
+ }
+ &:hover {
+ figcaption {
+ // As far as I can see there is no way to darken/lighten a text color
+ // defined by MDL, due to the "unqote" functions.
+ // So this is a hack
+ color: rgba(0, 0, 0, 1) !important;
+ background-color: rgba(255, 255, 255, 0.25);
+ }
+ }
+ }
+
+ .mdlext-carousel__slide__ripple-container {
+ text-decoration: none;
+ display: block;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ outline: 0;
+
+ & .mdl-ripple {
+ background: $mdlext-carousel-slide-ripple-color;
+ }
+ }
+}
+
+
diff --git a/node_modules/mdl-ext/src/carousel/carousel.js b/node_modules/mdl-ext/src/carousel/carousel.js
new file mode 100644
index 0000000..8fe59e1
--- /dev/null
+++ b/node_modules/mdl-ext/src/carousel/carousel.js
@@ -0,0 +1,726 @@
+/**
+ * @license
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+/**
+ * Image carousel
+ */
+
+import intervalFunction from '../utils/interval-function';
+import { inOutQuintic } from '../utils/easing';
+import { jsonStringToObject} from '../utils/json-utils';
+import {
+ VK_TAB,
+ VK_ENTER,
+ VK_ESC,
+ VK_SPACE,
+ VK_PAGE_UP,
+ VK_PAGE_DOWN,
+ VK_END,
+ VK_HOME,
+ VK_ARROW_LEFT,
+ VK_ARROW_UP,
+ VK_ARROW_RIGHT,
+ VK_ARROW_DOWN,
+ IS_UPGRADED,
+ IS_FOCUSED,
+ MDL_RIPPLE,
+ MDL_RIPPLE_COMPONENT,
+ MDL_RIPPLE_EFFECT,
+ MDL_RIPPLE_EFFECT_IGNORE_EVENTS
+} from '../utils/constants';
+
+const MDL_RIPPLE_CONTAINER = 'mdlext-carousel__slide__ripple-container';
+
+
+(function() {
+ 'use strict';
+
+ //const CAROUSEL = 'mdlext-carousel';
+ const SLIDE = 'mdlext-carousel__slide';
+ const ROLE = 'list';
+ const SLIDE_ROLE = 'listitem';
+
+
+ /**
+ * @constructor
+ * @param {Element} element The element that will be upgraded.
+ */
+ const MaterialExtCarousel = function MaterialExtCarousel(element) {
+ // Stores the element.
+ this.element_ = element;
+
+ // Default config
+ this.config_ = {
+ interactive : true,
+ autostart : false,
+ type : 'slide',
+ interval : 1000,
+ animationLoop: intervalFunction(1000)
+ };
+
+ this.scrollAnimation_ = intervalFunction(33);
+
+ // Initialize instance.
+ this.init();
+ };
+
+ window['MaterialExtCarousel'] = MaterialExtCarousel;
+
+
+ /**
+ * Start slideshow animation
+ * @private
+ */
+ MaterialExtCarousel.prototype.startSlideShow_ = function() {
+
+ const nextSlide = () => {
+ let slide = this.element_.querySelector(`.${SLIDE}[aria-selected]`);
+ if(slide) {
+ slide.removeAttribute('aria-selected');
+ slide = slide.nextElementSibling;
+ }
+ if(!slide) {
+ slide = this.element_.querySelector(`.${SLIDE}:first-child`);
+ this.animateScroll_(0);
+ }
+ if(slide) {
+ this.moveSlideIntoViewport_(slide);
+ slide.setAttribute('aria-selected', '');
+ this.emitSelectEvent_('next', null, slide);
+ return true;
+ }
+ return false;
+ };
+
+ const nextScroll = direction => {
+ let nextDirection = direction;
+
+ if('next' === direction && this.element_.scrollLeft === this.element_.scrollWidth - this.element_.clientWidth) {
+ nextDirection = 'prev';
+ }
+ else if(this.element_.scrollLeft === 0) {
+ nextDirection = 'next';
+ }
+ const x = 'next' === nextDirection
+ ? Math.min(this.element_.scrollLeft + this.element_.clientWidth, this.element_.scrollWidth - this.element_.clientWidth)
+ : Math.max(this.element_.scrollLeft - this.element_.clientWidth, 0);
+
+ this.animateScroll_(x, 1000);
+ return nextDirection;
+ };
+
+
+ if(!this.config_.animationLoop.started) {
+ this.config_.animationLoop.interval = this.config_.interval;
+ let direction = 'next';
+
+ if('scroll' === this.config_.type) {
+ this.config_.animationLoop.start( () => {
+ direction = nextScroll(direction);
+ return true; // It runs until cancelSlideShow_ is triggered
+ });
+ }
+ else {
+ nextSlide();
+ this.config_.animationLoop.start( () => {
+ return nextSlide(); // It runs until cancelSlideShow_ is triggered
+ });
+ }
+ }
+
+ // TODO: Pause animation when carousel is not in browser viewport or user changes tab
+ };
+
+ /**
+ * Cancel slideshow if running. Emmits a 'pause' event
+ * @private
+ */
+ MaterialExtCarousel.prototype.cancelSlideShow_ = function() {
+ if(this.config_.animationLoop.started) {
+ this.config_.animationLoop.stop();
+ this.emitSelectEvent_('pause', VK_ESC, this.element_.querySelector(`.${SLIDE}[aria-selected]`));
+ }
+ };
+
+ /**
+ * Animate scroll
+ * @param newPosition
+ * @param newDuration
+ * @param completedCallback
+ * @private
+ */
+ MaterialExtCarousel.prototype.animateScroll_ = function( newPosition, newDuration, completedCallback ) {
+
+ const start = this.element_.scrollLeft;
+ const distance = newPosition - start;
+
+ if(distance !== 0) {
+ const duration = Math.max(Math.min(Math.abs(distance), newDuration||400), 100); // duration is between 100 and newDuration||400ms||distance
+ let t = 0;
+ this.scrollAnimation_.stop();
+ this.scrollAnimation_.start( timeElapsed => {
+ t += timeElapsed;
+ if(t < duration) {
+ this.element_.scrollLeft = inOutQuintic(t, start, distance, duration);
+ return true;
+ }
+ else {
+ this.element_.scrollLeft = newPosition;
+ if(completedCallback) {
+ completedCallback();
+ }
+ return false;
+ }
+ });
+ }
+ else {
+ if(completedCallback) {
+ completedCallback();
+ }
+ }
+ };
+
+ /**
+ * Execute commend
+ * @param event
+ * @private
+ */
+ MaterialExtCarousel.prototype.command_ = function( event ) {
+ let x = 0;
+ let slide = null;
+ const a = event.detail.action.toLowerCase();
+
+ // Cancel slideshow if running
+ this.cancelSlideShow_();
+
+ switch (a) {
+ case 'first':
+ slide = this.element_.querySelector(`.${SLIDE}:first-child`);
+ break;
+
+ case 'last':
+ x = this.element_.scrollWidth - this.element_.clientWidth;
+ slide = this.element_.querySelector(`.${SLIDE}:last-child`);
+ break;
+
+ case 'scroll-prev':
+ x = Math.max(this.element_.scrollLeft - this.element_.clientWidth, 0);
+ break;
+
+ case 'scroll-next':
+ x = Math.min(this.element_.scrollLeft + this.element_.clientWidth, this.element_.scrollWidth - this.element_.clientWidth);
+ break;
+
+ case 'next':
+ case 'prev':
+ slide = this.element_.querySelector(`.${SLIDE}[aria-selected]`);
+ if(slide) {
+ slide = a === 'next' ? slide.nextElementSibling : slide.previousElementSibling;
+ this.setAriaSelected_(slide);
+ this.emitSelectEvent_(a, null, slide);
+ }
+ return;
+
+ case 'play':
+ Object.assign(this.config_, event.detail);
+ this.startSlideShow_();
+ return;
+
+ case 'pause':
+ return;
+
+ default:
+ return;
+ }
+
+ this.animateScroll_(x, undefined, () => {
+ if ('scroll-next' === a || 'scroll-prev' === a) {
+ const slides = this.getSlidesInViewport_();
+ if (slides.length > 0) {
+ slide = 'scroll-next' === a ? slides[0] : slides[slides.length - 1];
+ }
+ }
+ this.setAriaSelected_(slide);
+ this.emitSelectEvent_(a, null, slide);
+ });
+ };
+
+ /**
+ * Handles custom command event, 'scroll-prev', 'scroll-next', 'first', 'last', next, prev, play, pause
+ * @param event. A custom event
+ * @private
+ */
+ MaterialExtCarousel.prototype.commandHandler_ = function( event ) {
+ event.preventDefault();
+ event.stopPropagation();
+ if(event.detail && event.detail.action) {
+ this.command_(event);
+ }
+ };
+
+ /**
+ * Handle keypress
+ * @param event
+ * @private
+ */
+ MaterialExtCarousel.prototype.keyDownHandler_ = function(event) {
+
+ if (event && event.target && event.target !== this.element_) {
+
+ let action = 'first';
+
+ if ( event.keyCode === VK_HOME || event.keyCode === VK_END
+ || event.keyCode === VK_PAGE_UP || event.keyCode === VK_PAGE_DOWN) {
+
+ event.preventDefault();
+ if (event.keyCode === VK_END) {
+ action = 'last';
+ }
+ else if (event.keyCode === VK_PAGE_UP) {
+ action = 'scroll-prev';
+ }
+ else if (event.keyCode === VK_PAGE_DOWN) {
+ action = 'scroll-next';
+ }
+
+ const cmd = new CustomEvent('select', {
+ detail: {
+ action: action,
+ }
+ });
+ this.command_(cmd);
+ }
+ else if ( event.keyCode === VK_TAB
+ || event.keyCode === VK_ENTER || event.keyCode === VK_SPACE
+ || event.keyCode === VK_ARROW_UP || event.keyCode === VK_ARROW_LEFT
+ || event.keyCode === VK_ARROW_DOWN || event.keyCode === VK_ARROW_RIGHT) {
+
+ let slide = getSlide_(event.target);
+
+ if(!slide) {
+ return;
+ }
+
+ // Cancel slideshow if running
+ this.cancelSlideShow_();
+
+ switch (event.keyCode) {
+ case VK_ARROW_UP:
+ case VK_ARROW_LEFT:
+ action = 'prev';
+ slide = slide.previousElementSibling;
+ break;
+
+ case VK_ARROW_DOWN:
+ case VK_ARROW_RIGHT:
+ action = 'next';
+ slide = slide.nextElementSibling;
+ break;
+
+ case VK_TAB:
+ if (event.shiftKey) {
+ action = 'prev';
+ slide = slide.previousElementSibling;
+ }
+ else {
+ action = 'next';
+ slide = slide.nextElementSibling;
+ }
+ break;
+
+ case VK_SPACE:
+ case VK_ENTER:
+ action = 'select';
+ break;
+ }
+
+ if(slide) {
+ event.preventDefault();
+ setFocus_(slide);
+ this.emitSelectEvent_(action, event.keyCode, slide);
+ }
+ }
+ }
+ };
+
+ /**
+ * Handle dragging
+ * @param event
+ * @private
+ */
+ MaterialExtCarousel.prototype.dragHandler_ = function(event) {
+ event.preventDefault();
+
+ // Cancel slideshow if running
+ this.cancelSlideShow_();
+
+ let updating = false;
+ let rAFDragId = 0;
+
+ const startX = event.clientX || (event.touches !== undefined ? event.touches[0].clientX : 0);
+ let prevX = startX;
+ const targetElement = event.target;
+
+ const update = e => {
+ const currentX = (e.clientX || (e.touches !== undefined ? e.touches[0].clientX : 0));
+ const dx = prevX - currentX;
+
+ if(dx < 0) {
+ this.element_.scrollLeft = Math.max(this.element_.scrollLeft + dx, 0);
+ }
+ else if(dx > 0) {
+ this.element_.scrollLeft = Math.min(this.element_.scrollLeft + dx, this.element_.scrollWidth - this.element_.clientWidth);
+ }
+
+ prevX = currentX;
+ updating = false;
+ };
+
+ // drag handler
+ const drag = e => {
+ e.preventDefault();
+
+ if(!updating) {
+ rAFDragId = window.requestAnimationFrame( () => update(e));
+ updating = true;
+ }
+ };
+
+ // end drag handler
+ const endDrag = e => {
+ e.preventDefault();
+
+ this.element_.removeEventListener('mousemove', drag);
+ this.element_.removeEventListener('touchmove', drag);
+ window.removeEventListener('mouseup', endDrag);
+ window.removeEventListener('touchend', endDrag);
+
+ // cancel any existing drag rAF, see: http://www.html5rocks.com/en/tutorials/speed/animations/
+ window.cancelAnimationFrame(rAFDragId);
+
+ const slide = getSlide_(targetElement);
+ setFocus_(slide);
+ this.emitSelectEvent_('click', null, slide);
+ };
+
+ this.element_.addEventListener('mousemove', drag);
+ this.element_.addEventListener('touchmove', drag);
+ window.addEventListener('mouseup', endDrag);
+ window.addEventListener('touchend',endDrag);
+ };
+
+ /**
+ * Handle click
+ * @param event
+ * @private
+ */
+ MaterialExtCarousel.prototype.clickHandler_ = function(event) {
+ // Click is handled by drag
+ event.preventDefault();
+ };
+
+ /**
+ * Handle focus
+ * @param event
+ * @private
+ */
+ MaterialExtCarousel.prototype.focusHandler_ = function(event) {
+ const slide = getSlide_(event.target);
+ if(slide) {
+ // The last focused/selected slide has 'aria-selected', even if focus is lost
+ this.setAriaSelected_(slide);
+ slide.classList.add(IS_FOCUSED);
+ }
+ };
+
+ /**
+ * Handle blur
+ * @param event
+ * @private
+ */
+ MaterialExtCarousel.prototype.blurHandler_ = function(event) {
+ const slide = getSlide_(event.target);
+ if(slide) {
+ slide.classList.remove(IS_FOCUSED);
+ }
+ };
+
+ /**
+ * Emits a custeom 'select' event
+ * @param command
+ * @param keyCode
+ * @param slide
+ * @private
+ */
+ MaterialExtCarousel.prototype.emitSelectEvent_ = function(command, keyCode, slide) {
+
+ if(slide) {
+ this.moveSlideIntoViewport_(slide);
+
+ const evt = new CustomEvent('select', {
+ bubbles: true,
+ cancelable: true,
+ detail: {
+ command: command,
+ keyCode: keyCode,
+ source: slide
+ }
+ });
+ this.element_.dispatchEvent(evt);
+ }
+ };
+
+ /**
+ * Get the first visible slide in component viewport
+ * @private
+ */
+ MaterialExtCarousel.prototype.getSlidesInViewport_ = function() {
+ const carouselRect = this.element_.getBoundingClientRect();
+
+ const slidesInViewport = [...this.element_.querySelectorAll(`.${SLIDE}`)].filter( slide => {
+ const slideRect = slide.getBoundingClientRect();
+ return slideRect.left >= carouselRect.left && slideRect.right <= carouselRect.right;
+ });
+ return slidesInViewport;
+ };
+
+ /**
+ * Move slide into component viewport - if needed
+ * @param slide
+ * @private
+ */
+ MaterialExtCarousel.prototype.moveSlideIntoViewport_ = function(slide) {
+ const carouselRect = this.element_.getBoundingClientRect();
+ const slideRect = slide.getBoundingClientRect();
+
+ if(slideRect.left < carouselRect.left) {
+ const x = this.element_.scrollLeft - (carouselRect.left - slideRect.left);
+ this.animateScroll_(x);
+ }
+ else if(slideRect.right > carouselRect.right) {
+ const x = this.element_.scrollLeft - (carouselRect.right - slideRect.right);
+ this.animateScroll_(x);
+ }
+ };
+
+
+ /**
+ * Removes 'aria-selected' from all slides in carousel
+ * @private
+ */
+ MaterialExtCarousel.prototype.setAriaSelected_ = function(slide) {
+ if(slide) {
+ [...this.element_.querySelectorAll(`.${SLIDE}[aria-selected]`)].forEach(
+ slide => slide.removeAttribute('aria-selected')
+ );
+ slide.setAttribute('aria-selected', '');
+ }
+ };
+
+ /**
+ * Removes event listeners
+ * @private
+ */
+ MaterialExtCarousel.prototype.removeListeners_ = function() {
+ this.element_.removeEventListener('focus', this.focusHandler_);
+ this.element_.removeEventListener('blur', this.blurHandler_);
+ this.element_.removeEventListener('keydown', this.keyDownHandler_);
+ this.element_.removeEventListener('mousedown', this.dragHandler_);
+ this.element_.removeEventListener('touchstart', this.dragHandler_);
+ this.element_.removeEventListener('click', this.clickHandler_, false);
+ this.element_.removeEventListener('command', this.commandHandler_);
+ this.element_.removeEventListener('mdl-componentdowngraded', this.mdlDowngrade_);
+ };
+
+
+ // Helpers
+ const getSlide_ = element => {
+ return element.closest(`.${SLIDE}`);
+ };
+
+ const setFocus_ = slide => {
+ if(slide) {
+ slide.focus();
+ }
+ };
+
+ const addRipple_ = slide => {
+ if(!slide.querySelector(`.${MDL_RIPPLE_CONTAINER}`)) {
+ const rippleContainer = document.createElement('span');
+ rippleContainer.classList.add(MDL_RIPPLE_CONTAINER);
+ rippleContainer.classList.add(MDL_RIPPLE_EFFECT);
+ const ripple = document.createElement('span');
+ ripple.classList.add(MDL_RIPPLE);
+ rippleContainer.appendChild(ripple);
+
+ const img = slide.querySelector('img');
+ if (img) {
+ // rippleContainer blocks image title
+ rippleContainer.title = img.title;
+ }
+ slide.appendChild(rippleContainer);
+ componentHandler.upgradeElement(rippleContainer, MDL_RIPPLE_COMPONENT);
+ }
+ };
+ // End helpers
+
+
+ // Public methods.
+
+ /**
+ * Cancel animation - if running.
+ *
+ * @public
+ */
+ MaterialExtCarousel.prototype.stopAnimation = function() {
+ this.config_.animationLoop.stop();
+ };
+ MaterialExtCarousel.prototype['stopAnimation'] = MaterialExtCarousel.prototype.stopAnimation;
+
+
+ /**
+ * Upgrade slides
+ * Use if more list elements are added later (dynamically)
+ *
+ * @public
+ */
+ MaterialExtCarousel.prototype.upgradeSlides = function() {
+
+ const hasRippleEffect = this.element_.classList.contains(MDL_RIPPLE_EFFECT);
+
+ [...this.element_.querySelectorAll(`.${SLIDE}`)].forEach( slide => {
+
+ slide.setAttribute('role', SLIDE_ROLE);
+
+ if(this.config_.interactive) {
+ if(!slide.getAttribute('tabindex')) {
+ slide.setAttribute('tabindex', '0');
+ }
+ if (hasRippleEffect) {
+ addRipple_(slide);
+ }
+ }
+ else {
+ slide.setAttribute('tabindex', '-1');
+ }
+ });
+ };
+ MaterialExtCarousel.prototype['upgradeSlides'] = MaterialExtCarousel.prototype.upgradeSlides;
+
+
+ /**
+ * Get config object
+ *
+ * @public
+ */
+ MaterialExtCarousel.prototype.getConfig = function() {
+ return this.config_;
+ };
+ MaterialExtCarousel.prototype['getConfig'] = MaterialExtCarousel.prototype.getConfig;
+
+ /**
+ * Initialize component
+ */
+ MaterialExtCarousel.prototype.init = function() {
+
+ if (this.element_) {
+ // Config
+ if(this.element_.hasAttribute('data-config')) {
+ this.config_ = jsonStringToObject(this.element_.getAttribute('data-config'), this.config_);
+ }
+
+ // Wai-Aria
+ this.element_.setAttribute('role', ROLE);
+
+ // Prefer tabindex -1
+ if(!Number.isInteger(this.element_.getAttribute('tabindex'))) {
+ this.element_.setAttribute('tabindex', -1);
+ }
+
+ // Remove listeners, just in case ...
+ this.removeListeners_();
+
+ if(this.config_.interactive) {
+
+ // Ripple
+ const hasRippleEffect = this.element_.classList.contains(MDL_RIPPLE_EFFECT);
+ if (hasRippleEffect) {
+ this.element_.classList.add(MDL_RIPPLE_EFFECT_IGNORE_EVENTS);
+ }
+
+ // Listen to focus/blur events
+ this.element_.addEventListener('focus', this.focusHandler_.bind(this), true);
+ this.element_.addEventListener('blur', this.blurHandler_.bind(this), true);
+
+ // Listen to keyboard events
+ this.element_.addEventListener('keydown', this.keyDownHandler_.bind(this), false);
+
+ // Listen to drag events
+ this.element_.addEventListener('mousedown', this.dragHandler_.bind(this), false);
+ this.element_.addEventListener('touchstart', this.dragHandler_.bind(this), false);
+
+ // Listen to click events
+ this.element_.addEventListener('click', this.clickHandler_.bind(this), false);
+ }
+
+ // Listen to custom 'command' event
+ this.element_.addEventListener('command', this.commandHandler_.bind(this), false);
+
+ // Listen to 'mdl-componentdowngraded' event
+ this.element_.addEventListener('mdl-componentdowngraded', this.mdlDowngrade_.bind(this));
+
+ // Slides collection
+ this.upgradeSlides();
+
+ // Set upgraded flag
+ this.element_.classList.add(IS_UPGRADED);
+
+ if(this.config_.autostart) {
+ // Start slideshow
+ this.startSlideShow_();
+ }
+ }
+ };
+
+ /*
+ * Downgrade component
+ * E.g remove listeners and clean up resources
+ */
+ MaterialExtCarousel.prototype.mdlDowngrade_ = function() {
+ 'use strict';
+ //console.log('***** MaterialExtCarousel.mdlDowngrade_');
+
+ // Stop animation - if any
+ this.stopAnimation();
+
+ // Remove listeners
+ this.removeListeners_();
+ };
+
+ // The component registers itself. It can assume componentHandler is available
+ // in the global scope.
+ /* eslint no-undef: 0 */
+ componentHandler.register({
+ constructor: MaterialExtCarousel,
+ classAsString: 'MaterialExtCarousel',
+ cssClass: 'mdlext-js-carousel',
+ widget: true
+ });
+})();
diff --git a/node_modules/mdl-ext/src/carousel/readme.md b/node_modules/mdl-ext/src/carousel/readme.md
new file mode 100644
index 0000000..6485972
--- /dev/null
+++ b/node_modules/mdl-ext/src/carousel/readme.md
@@ -0,0 +1,271 @@
+# Carousel
+
+![Carousel](../../etc/carousel.png)
+
+A responsive image carousel.
+
+## Introduction
+The Material Design Lite Ext (MDLEXT) Carousel, commonly also referred to as “slide shows” or “sliders”, is a component
+for cycling through a series of images. The carousel is defined and enclosed by a container element and
+distributes images horizontally, with repect to the available container size. Images outside the container viewport slides
+into view, triggerd by a user action or by running an animation loop (rAF).
+
+This component does not attempt in any way to resemble a three-dimensional image carousel that is used to show slides
+from a projector. The component is perceived more as a slider, but the terms slider and carousel, are often used
+interchangeably.
+
+### Features:
+* Navigate carousel using keyboard (arrow keys, tab, pgup, pgdown, home, end), mouse drag, touch events, or by sending custom events to the carousel (first, scroll-prev, prev, next, scroll-next, last, play, pause)
+* Select a particular image using enter or space key, or by clicking an image
+* Cycle images at a given interval - a slideshow
+* Set slideshow interval via a data attribute or as a part of the play custom event
+* Stop slideshow via custom event (pause) or by a user interaction, e.g clicking an image
+* User interactions via keyboard, mouse or touch events may be blocked, if configured
+* Start slideshow at component initialization using a data attribute
+* The carousel emits custom events reflecting a user action. E.g. clicking an image will emit a 'select' event with a detail object holding a reference to the selected image.
+
+### Limitations:
+* The carousel should pause any running animation on window.bur or tab.blur - not implemented
+* The carousel should pause any running animation when the carousel is not in window viewport - not implemented
+* Only horizontal layout in first release
+
+
+### To include a MDLEXT **carousel** component:
+ 1. Code a block element, e.g. a `<div>` element, to hold dimensions of the carousel.
+```html
+<div style="height: 200px; width: 100%;">
+</div>
+```
+
+ 2. Code a `<ul>` element with `class="mdlext-carousel mdlext-js-carousel"` to hold the carousel.
+```html
+<div style="height: 200px; width: 100%;">
+ <ul class="mdlext-carousel mdlext-js-carousel">
+ <ul>
+</div>
+```
+
+ 3. Code a `<li>` element with `class="mdlext-carousel__slide"` to hold an individual image (thumbnail).
+```html
+<div style="height: 200px; width: 100%;">
+ <ul class="mdlext-carousel mdlext-js-carousel">
+ <li class="mdlext-carousel__slide">
+ <li>
+ <ul>
+</div>
+```
+
+ 4. Code a `<figure>` element to hold the image and the image title.
+```html
+<div style="height: 200px; width: 100%;">
+ <ul class="mdlext-carousel mdlext-js-carousel">
+ <li class="mdlext-carousel__slide">
+ <figure>
+ </figure>
+ <li>
+ <ul>
+</div>
+```
+
+ 5. Inside the `<figure>` element add an `<img>` element with reference to the thumbnail image to be shown. Optionally add a `<figcaption>` element to hold the image title.
+```html
+<div style="height: 200px; width: 100%;">
+ <ul class="mdlext-carousel mdlext-js-carousel">
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="_D802591.jpg" title="Whooper swans in flight"/>
+ <figcaption>_D802591.jpg</figcaption>
+ </figure>
+ <li>
+ <ul>
+</div>
+```
+
+ 6. Repeat steps 3..5 for each slide required.
+
+### Examples
+* See: [snippets/carousel.html](./snippets/carousel.html)
+* Or try out the [live demo](http://leifoolsen.github.io/mdl-ext/demo/carousel.html)
+
+## Interactions
+
+### Keyboard interaction
+The carousel interacts with the following keyboard keys.
+
+* `Tab` - When focus is on a slide, pressing the `Tab` key moves focus in the following manner:
+ * If there is a next slide, focus moves to the next slide.
+ * If focus is on the last slide, focus moves to the first focusable element outside the carousel component.
+* `Shift+Tab` - Generally the reverse of `Tab`.
+* `Left arrow` - Moves focus to the previous slide. If the current slide is the first slide, focus stays on that slide.
+* `Right arrow` - Moves focus to the next slide. If the current slide is the last slide, focus stays on that slide.
+* `Up arrow` - behaves the same as left arrow.
+* `Down arrow` - behaves the same as right arrow.
+* `End` - When focus is on a slide, an `End` key press moves focus to the last slide.
+* `Home` - When focus is on a slide, a `Home` key press moves focus to the first slide.
+* `Enter/Space` - When focus is on a slide, pressing `Enter` or `Space` selects the focused slide.
+
+### Mouse / Touch interaction
+* `Drag or Swipe left` - Move slides outside container viewport into view.
+* `Drag or Swipe right` - Move slides outside container viewport into view
+
+
+## Component configuration
+The component can be configured using a `data-config` attribute. The attribute value is a JSON string with the following properties.
+
+| Property | | |
+|-----------------|----|----|
+| `interactive` | if `true`, the user can use keyboard or mouse to navigate the slides | default: `true` |
+| `autostart` | if `true`, the slideshow starts immediately after component initialization | default: `false` |
+| `type` | animation type, `'slide'`, advances one slide, `'scroll'`, moves next sequence of slides into view | default `'slide'` |
+| `interval` | animation interval, in milliseconds | default `1000` |
+
+
+The `data-config` attribute must be a valid JSON string. You can use single or double quotes for the JSON properties.
+
+Example 1, single quotes in JSON config string:
+```html
+<ul class="mdlext-carousel mdlext-js-carousel mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events"
+ data-config="{ 'interactive': true, 'autostart': false, 'type': 'slide', 'interval': 2000 }">
+ ......
+</ul>
+```
+
+Example 2, double quotes in JSON config string:
+```html
+<ul class="mdlext-carousel mdlext-js-carousel"
+ data-config='{ "interactive": false, "autostart": true, "type": "scroll", "interval": 5000 }'>
+ ......
+</ul>
+```
+
+## Events
+Interaction with the component programmatically is performed by sending events to the component, and receive responses
+from the component.
+
+### Events the component listenes to
+A client can send a `command` custom event to the carousel. The command event holds an action detail object defining
+the action to perform.
+
+```javascript
+new CustomEvent('command', { detail: { action : 'first' } });
+new CustomEvent('command', { detail: { action : 'scroll-prev' } });
+new CustomEvent('command', { detail: { action : 'prev' } });
+new CustomEvent('command', { detail: { action : 'next' } });
+new CustomEvent('command', { detail: { action : 'scroll-next' } });
+new CustomEvent('command', { detail: { action : 'last' } });
+new CustomEvent('command', { detail:
+ {
+ action : 'play',
+ interval: 3000 // Interval is optional, overrides value set by 'data-config'
+ }
+});
+new CustomEvent('command', { detail: { action : 'pause' } });
+
+// Trigger the event
+myCarousel.dispatchEvent(ev);
+```
+
+Refer to [snippets/lightbox.html](./snippets/carousel.html) for usage.
+
+### Events emitted
+When a user interacts with the component, or the component receives a `command` custom event, the component responds
+with a `select` custom event reflecting the action performed and a detail object holding the selected slide element.
+
+The `select` detail object has the following format:
+
+```javascript
+detail: {
+ command, // The command executed (`first`, `scroll-prev`, `prev`, `next`, `scroll-next`, `last`)
+ keyCode, // Key pressed, if any
+ source // The element that caused the event
+}
+```
+
+Set up a `select` listener.
+```javascript
+document.querySelector('#my-carousel').addEventListener('select', function(e) {
+ var selectedElement = e.detail.source;
+ console.log('Selected element', selectedElement);
+ var selectImage = selectedElement.querySelector('img');
+});
+
+```
+Refer to [snippets/lightbox.html](./snippets/carousel.html) for usage.
+
+
+## Public methods
+
+### `stopAnimation()`
+
+Stops animation - if any.
+
+### `upgradeSlides()`
+Upgrade slides. If you add slides to the carousel after the page has loaded, you must call `upgradeSlides` to
+notify the component about the newly inserted slides.
+
+```javascript
+myCarousel = document.querySelector('#my-carousel');
+myCarousel.MaterialExtCarousel.upgradeSlides();
+```
+
+### `getConfig()`
+Returns the `config` object.
+
+
+## Configuration options
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements to the carousel.
+The table below lists the available classes and their effects.
+
+| MDLEXT class | Effect | Remarks |
+|--------------|--------|---------|
+| `mdlext-carousel` | Defines a container as an MDLEXT carousel component | Required on `<ul>` element |
+| `mdlext-js-carousel` | Assigns basic MDL behavior to carousel | Required on `<ul>` element |
+| `mdlext-carousel__slide` | Defines a carousel slide | Required on `<li>` element |
+
+Attributes.
+
+| Attribute | Effect | Remarks |
+|-----------|--------|---------|
+| `data-config` | A JSON object defining startup configurations | |
+| `aria-selected` | The selected `mdlext-carousel__slide` element | Only one element can be selected at the same time |
+| `list` | The component add the role `list` to self | |
+| `listitem` | The component add the role `listitem` to `mdlext-carousel__slide` items | |
+
+
+## Note for single page applications
+If you use Material Design Lite in a dynamic page, e.g. a single page application, any running animations must be
+stopped before a page frament containing a carousel component is removed from the DOM. Call
+`componentHandler.downgradeElements` to stop any running animation and clean up component resources.
+In a static web application there should be no need to call `componentHandler.downgradeElements`.
+
+The following code snippet demonstrates how to properly clean up components before removing them from DOM.
+
+```javascript
+// Call 'componentHandler.downgradeElements' to clean up
+const content = document.querySelector('#content');
+const components = content.querySelectorAll('.is-upgraded');
+componentHandler.downgradeElements([...components]);
+
+// Remove elements from DOM.
+// See: http://jsperf.com/empty-an-element/16
+const removeChildElements = (element, forceReflow = true) => {
+ while (element.lastChild) {
+ element.removeChild(element.lastChild);
+ }
+ if(forceReflow) {
+ // See: http://jsperf.com/force-reflow
+ const d = element.style.display;
+ element.style.display = 'none';
+ element.style.display = d;
+ }
+}
+
+removeChildElements(content);
+```
+
+## How to use the component programmatically
+The [tests](../../test/carousel/carousel.spec.js) and the [snippets/lightbox.html](./snippets/carousel.html)
+code provides examples on how to use the component programmatically.
+
+## Reference
+[WCAG Carousel Concepts](https://www.w3.org/WAI/tutorials/carousels/)
diff --git a/node_modules/mdl-ext/src/carousel/snippets/carousel.html b/node_modules/mdl-ext/src/carousel/snippets/carousel.html
new file mode 100644
index 0000000..ac51213
--- /dev/null
+++ b/node_modules/mdl-ext/src/carousel/snippets/carousel.html
@@ -0,0 +1,612 @@
+<p><strong>Note:</strong> Does not work as expected in IE11</p>
+
+<style>
+ .carousel-demo {
+ box-sizing: border-box;
+ display: block;
+ padding: 4px;
+ border: 1px solid #dddddd;
+ border-radius: 4px;
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
+ }
+
+ .carousel-demo * {
+ box-sizing: border-box;
+ }
+
+ #carousel-imgviewer {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+ }
+
+ #carousel-imgviewer figure {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ -webkit-box-pack: center;
+ -ms-flex-pack: center;
+ justify-content: center;
+
+ position: relative;
+ height: 100%;
+ padding: 0;
+ margin: 0;
+ }
+
+ #carousel-imgviewer figure img {
+ width: auto;
+ max-width: 100%;
+ max-height: 100%;
+ border: 0;
+ outline: 0;
+
+ -webkit-animation: fade-in-element 0.25s ease-out;
+ -moz-animation: fade-in-element 0.25s ease-out;
+ -o-animation: fade-in-element 025s ease-out;
+ animation: fade-in-element 0.25s ease-out;
+ }
+
+ #carousel-footer {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-pack: justify;
+ -ms-flex-pack: justify;
+ justify-content: space-between;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ }
+
+ #carousel-footer .mdl-card__supporting-text {
+ -webkit-box-flex: 1;
+ -ms-flex: 1;
+ flex: 1;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ padding: 0;
+ width: 100%;
+ }
+
+ #carousel-footer nav {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ }
+
+ .carousel-button {
+ }
+ .carousel-button__icon {
+ font-size: 24px;
+ }
+
+ #carousel-container {
+ }
+
+ @media (max-width: 479px) {
+ #carousel-imgviewer {
+ height: 260px;
+ }
+ .carousel-button {
+ width: 28px;
+ min-width: 28px;
+ height: 28px;
+ }
+ .carousel-button__icon {
+ font-size: 20px;
+ }
+ #carousel-container {
+ height: 60px;
+ margin-top: 4px;
+ }
+ }
+
+ @media (min-width: 480px) and (max-width: 839px) {
+ #carousel-imgviewer {
+ height: 360px;
+ }
+ #carousel-container {
+ height: 90px;
+ }
+ }
+
+ @media (min-width: 840px) {
+ #carousel-imgviewer {
+ height: 500px;
+ }
+ #carousel-container {
+ height: 110px;
+ }
+ }
+
+ @-webkit-keyframes fade-in-element {
+ 0% { opacity: 0; }
+ 100% { opacity: 1; }
+ }
+ @-moz-keyframes fade-in-element {
+ 0% { opacity: 0; }
+ 100% { opacity: 1; }
+ }
+ @-o-keyframes fade-in-element {
+ 0% { opacity: 0; }
+ 100% { opacity: 1; }
+ }
+ @keyframes fade-in-element {
+ 0% { opacity: 0; }
+ 100% { opacity: 1; }
+ }
+
+</style>
+
+<artichle class="carousel-demo" style="height: 64px; margin-bottom: 16px; padding-top: 1px;">
+ <ul class="mdlext-carousel mdlext-js-carousel"
+ data-config="{ 'interactive': false, 'autostart': true, 'type': 'scroll', 'interval': 5000 }">
+
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D802141.jpg" title="Northern goshawk with prey"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D802143.jpg" title="Northern goshawk with prey"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D802591.jpg" title="Whooper swans in flight"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D804370-3.jpg" title="European green woodpecker"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D808689.jpg" title="The bridge"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D802181.jpg" title="Landscape in blue pastel"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D800912.jpg" title="Hiking the mountains of Dovre"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D809453-_D809457-4.jpg" title="The Polar Express. End of Line. Ny Aalesund, Spitsbergen" />
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_DSC8214.jpg" title="Still got the blues"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D800017.jpg" title="Flowers"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D800023.jpg" title="Red-breasted merganser"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D800851.jpg" title="Musk oxes, Dovre, Norway"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D800166.jpg" title="Arctic Fox, Svalbard, Norway" />
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D800951.jpg" title="Fly fishing the arctic waters, Svalbard, Norway"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D801188.jpg" title="Lady of the snows (Pulsatilla vernalis), Dovre, Norway"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D801205-2.jpg" title="PULSE, Kilden Consert Hall, Kristiansand"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D801274.jpg" title="PULSE, Kilden Consert Hall, Kristiansand"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D801392.jpg" title="Peregrine falcon, Norway"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D801436.jpg" title="Peregrine falcon, Norway"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D801952-4.jpg" title="Mr. Per E Knudsen"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D807603.jpg" title="Black Woodpecker"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D807689.jpg" title="Goshina"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D807558.jpg" title="Goshina"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D800464.jpg" title="Svalbard Rock ptarmigan"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_DSC7535.jpg" title="Nice, France"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D802478.jpg" title="Cheetah, Bloemfontain, South Africa"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D800698.jpg" title="Red Squirrel"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D803118.jpg" title="Milky Way, Bloemfontain, South Africa"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D803521.jpg" title="Winter Light, Senja, Norway"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D803465-3.jpg" title="Selfie with Aurora B :)"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D806374.jpg" title="Lista Lighthouse, Norway"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D805345-12.jpg" title="Osprey"/>
+ </figure>
+ </li>
+ </ul>
+</artichle>
+
+
+
+
+<artichle class="carousel-demo">
+
+ <section id="carousel-imgviewer">
+ <figure>
+ <img src="./images/_D802143-2.jpg" alt="" title=""/>
+ </figure>
+ </section>
+
+ <footer id="carousel-footer">
+ <div id="carousel-viewer-title" class="mdl-card__supporting-text">Northern goshawk with prey</div>
+ <nav>
+ <button id="carousel-btn-first" class="mdl-button mdl-button--icon mdl-js-button carousel-button" title="Scroll First">
+ <i class="material-icons carousel-button__icon">first_page</i>
+ </button>
+ <button id="carousel-btn-scroll-prev" class="mdl-button mdl-button--icon mdl-js-button carousel-button" title="Scroll Previous">
+ <i class="material-icons carousel-button__icon">fast_rewind</i>
+ </button>
+ <button id="carousel-btn-prev" class="mdl-button mdl-button--icon mdl-js-button carousel-button" title="Previous">
+ <i class="material-icons carousel-button__icon">navigate_before</i>
+ </button>
+ <button id="carousel-btn-play-pause" class="mdl-button mdl-button--icon mdl-js-button carousel-button" title="Play">
+ <i class="material-icons carousel-button__icon">play_circle_outline</i>
+ </button>
+ <button id="carousel-btn-next" class="mdl-button mdl-button--icon mdl-js-button carousel-button" title="Next">
+ <i class="material-icons carousel-button__icon">navigate_next</i>
+ </button>
+ <button id="carousel-btn-scroll-next" class="mdl-button mdl-button--icon mdl-js-button carousel-button" title="Scroll Next">
+ <i class="material-icons carousel-button__icon">fast_forward</i>
+ </button>
+ <button id="carousel-btn-last" class="mdl-button mdl-button--icon mdl-js-button carousel-button" title="Scroll Last">
+ <i class="material-icons carousel-button__icon">last_page</i>
+ </button>
+ </nav>
+ </footer>
+
+ <section id="carousel-container">
+ <ul id="mdlext-carousel-demo2" class="mdlext-carousel mdlext-js-carousel mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events">
+ <li class="mdlext-carousel__slide" aria-selected >
+ <a href="./images/_D802143-2.jpg">
+ <figure>
+ <img src="./images/_D802143.jpg" title="Northern goshawk with prey"/>
+ <figcaption>_D802143.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <a href="./images/_D802591-2.jpg">
+ <figure>
+ <img src="./images/_D802591.jpg" title="Whooper swans in flight"/>
+ <figcaption>_D802591.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D802181.jpg" title="Landscape in blue pastel"/>
+ <figcaption>_D802181.jpg</figcaption>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <a href="./images/_D809453-_D809457-3.jpg">
+ <figure>
+ <img src="./images/_D809453-_D809457-4.jpg" title="The Polar Express. End of Line. Ny Aalesund, Spitsbergen" />
+ <figcaption>_D809453</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <a href="./images/_DSC8214-2.jpg">
+ <figure>
+ <img src="./images/_DSC8214.jpg" title="Still got the blues"/>
+ <figcaption>_DSC8214.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <a href="./images/_D800166-2.jpg">
+ <figure>
+ <img src="./images/_D800166.jpg" title="Arctic Fox, Svalbard, Norway" />
+ <figcaption>_D800166.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <a href="./images/_D801392-2.jpg">
+ <figure>
+ <img src="./images/_D801392.jpg" title="Peregrine falcon, Norway"/>
+ <figcaption>_D801392.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <a href="./images/_D801436-2.jpg">
+ <figure>
+ <img src="./images/_D801436.jpg" title="Peregrine falcon, Norway"/>
+ <figcaption>_D801436.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D807558.jpg" title="Goshina"/>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <a href="./images/_D800464.jpg">
+ <figure>
+ <img src="./images/_D800464.jpg" title="Svalbard Rock ptarmigan"/>
+ <figcaption>_D800464.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <a href="./images/_DSC7535-2.jpg">
+ <figure>
+ <img src="./images/_DSC7535.jpg" title="Nice, France"/>
+ <figcaption>_DSC7535.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D802478.jpg" title="Cheetah, Bloemfontain, South Africa"/>
+ <figcaption>_D802478.jpg</figcaption>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D800698.jpg" title="Red Squirrel"/>
+ <figcaption>_D800698.jpg</figcaption>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D803118.jpg" title="Milky Way, Bloemfontain, South Africa"/>
+ <figcaption>_D803118.jpg</figcaption>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D803521.jpg" title="Winter Light, Senja, Norway"/>
+ <figcaption>_D803521.jpg</figcaption>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D803465-3.jpg" title="Selfie with Aurora B :)"/>
+ <figcaption>_D803465.jpg</figcaption>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D806374.jpg" title="Lista Lighthouse, Norway"/>
+ <figcaption>_D806374.jpg</figcaption>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D801087.jpg" title="Brokke, Norway"/>
+ <figcaption>_D801087.jpg</figcaption>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D803221.jpg" title="Mnt. Seglan, Senja, Norway"/>
+ <figcaption>_D803221.jpg</figcaption>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D803759.jpg" title="Fruit bat, Mauritius"/>
+ <figcaption>_D803759.jpg</figcaption>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D809758-2.jpg" title="Polar bear, Svalbard, Norway"/>
+ <figcaption>_D809758.jpg</figcaption>
+ </figure>
+ </li>
+ <li class="mdlext-carousel__slide">
+ <figure>
+ <img src="./images/_D805345-12.jpg" title="Osprey"/>
+ <figcaption>_D805345.jpg</figcaption>
+ </figure>
+ </li>
+ </ul>
+ </section>
+</artichle>
+
+
+<div style="margin-top: 8px">
+ <button id="btn-add-image" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--raised mdl-button--colored">
+ Add image to carousel
+ </button>
+ <p class="mdl-typography--caption" style="margin-top: 8px">
+ Click the button to add a new image to the carousel. Move to the inserted
+ image and click it. It should have ripple effect if upgraded correctly.
+ </p>
+</div>
+
+<p class="mdl-typography--caption" style="margin-top: 32px;">
+ All images appearing in this page are the exclusive property of Leif Olsen and are protected under the United States
+ and International Copyright laws. The images may not be reproduced or manipulated without the written permission of
+ Leif Olsen. Use of any image as the basis for another photographic concept or illustration (digital, artist rendering
+ or alike) is a violation of the United States and International Copyright laws. All images are copyrighted © Leif Olsen, 2016.
+</p>
+
+
+<script>
+ (function() {
+ 'use strict';
+
+ window.addEventListener('load', function() {
+
+ document.querySelector('#carousel-btn-first').addEventListener('click', function (e) {
+ var ev = new CustomEvent('command', {detail: {action: 'first'}});
+ document.querySelector('#mdlext-carousel-demo2').dispatchEvent(ev);
+ });
+
+ document.querySelector('#carousel-btn-scroll-prev').addEventListener('click', function (e) {
+ var ev = new CustomEvent('command', {detail: {action: 'scroll-prev'}});
+ document.querySelector('#mdlext-carousel-demo2').dispatchEvent(ev);
+ });
+
+ document.querySelector('#carousel-btn-prev').addEventListener('click', function (e) {
+ var ev = new CustomEvent('command', {detail: {action: 'prev'}});
+ document.querySelector('#mdlext-carousel-demo2').dispatchEvent(ev);
+ });
+
+ document.querySelector('#carousel-btn-next').addEventListener('click', function (e) {
+ var ev = new CustomEvent('command', {detail: {action: 'next'}});
+ document.querySelector('#mdlext-carousel-demo2').dispatchEvent(ev);
+ });
+
+ document.querySelector('#carousel-btn-scroll-next').addEventListener('click', function (e) {
+ var ev = new CustomEvent('command', {detail: {action: 'scroll-next'}});
+ document.querySelector('#mdlext-carousel-demo2').dispatchEvent(ev);
+ });
+
+ document.querySelector('#carousel-btn-last').addEventListener('click', function (e) {
+ var ev = new CustomEvent('command', {detail: {action: 'last'}});
+ document.querySelector('#mdlext-carousel-demo2').dispatchEvent(ev);
+ });
+
+ document.querySelector('#carousel-btn-play-pause').addEventListener('click', function (e) {
+ // Toggle play icon
+ var i = this.querySelector('i');
+ var action = i.innerText === 'play_circle_outline' ? 'play' : 'pause';
+ i.textContent = action === 'play' ? 'pause_circle_outline' : 'play_circle_outline';
+
+ var ev = new CustomEvent('command', {detail: {action: action, interval: 3000}});
+ document.querySelector('#mdlext-carousel-demo2').dispatchEvent(ev);
+ });
+
+ document.querySelector('#mdlext-carousel-demo2').addEventListener('select', function (e) {
+
+ if ('pause' === e.detail.command) {
+ // Set play icon
+ var i = document.querySelector('#carousel-btn-play-pause i');
+ i.textContent = 'play_circle_outline';
+ }
+ else {
+ var oldImage = document.querySelector('#carousel-imgviewer img');
+ var selectImage = e.detail.source.querySelector('img');
+ var selectImageSrc = selectImage.src;
+ if (e.detail.source.querySelector('a')) {
+ selectImageSrc = e.detail.source.querySelector('a').href;
+ }
+
+ if (selectImageSrc !== oldImage.src) {
+ var newImage = oldImage.cloneNode(true);
+ newImage.src = selectImageSrc;
+ oldImage.parentNode.replaceChild(newImage, oldImage);
+
+ var title = document.querySelector('#carousel-viewer-title');
+ title.textContent = selectImage.title;
+ }
+ }
+ });
+
+ document.querySelector('#btn-add-image').addEventListener('click', function (e) {
+ var slide_fragment = '<li class="mdlext-carousel__slide"><figure><img src="./images/_D809914-2.jpg" alt="Humpback whale" title="Humpback whale"/></figure></li>';
+ var carousel = document.querySelector('#mdlext-carousel-demo2');
+ carousel.insertAdjacentHTML('beforeend', slide_fragment);
+ carousel.MaterialExtCarousel.upgradeSlides();
+ });
+
+ });
+
+ }());
+
+</script>
diff --git a/node_modules/mdl-ext/src/collapsible/_collapsible.scss b/node_modules/mdl-ext/src/collapsible/_collapsible.scss
new file mode 100644
index 0000000..745676d
--- /dev/null
+++ b/node_modules/mdl-ext/src/collapsible/_collapsible.scss
@@ -0,0 +1,36 @@
+@charset "UTF-8";
+
+/**
+ * @license
+ * Copyright 2016-2017 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+.mdlext-collapsible {
+ box-sizing: border-box;
+ cursor: pointer;
+}
+
+.mdlext-collapsible-group,
+.mdlext-collapsible-region {
+ box-sizing: border-box;
+
+ &[hidden] {
+ @include mdlext-visually-hidden;
+ pointer-events: none;
+ }
+}
diff --git a/node_modules/mdl-ext/src/collapsible/collapsible.js b/node_modules/mdl-ext/src/collapsible/collapsible.js
new file mode 100644
index 0000000..862fffb
--- /dev/null
+++ b/node_modules/mdl-ext/src/collapsible/collapsible.js
@@ -0,0 +1,437 @@
+/**
+ * @license
+ * Copyright 2016-2017 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+
+/**
+ * A collapsible is a component to mark expandable and collapsible regions.
+ * The component use the aria-expanded state to indicate whether regions of
+ * the content are collapsible, and to expose whether a region is currently
+ * expanded or collapsed.
+ * @see https://www.w3.org/WAI/GL/wiki/Using_the_WAI-ARIA_aria-expanded_state_to_mark_expandable_and_collapsible_regions
+ */
+
+import {
+ IS_UPGRADED,
+ VK_SPACE,
+ VK_ENTER,
+} from '../utils/constants';
+
+import { randomString } from '../utils/string-utils';
+import { getParentElements, isFocusable } from '../utils/dom-utils';
+
+const JS_COLLAPSIBLE = 'mdlext-js-collapsible';
+const COLLAPSIBLE_CONTROL_CLASS = 'mdlext-collapsible';
+const COLLAPSIBLE_GROUP_CLASS = 'mdlext-collapsible-group';
+const COLLAPSIBLE_REGION_CLASS = 'mdlext-collapsible-region';
+
+/**
+ * The collapsible component
+ */
+
+class Collapsible {
+ element_ = null;
+ controlElement_ = null;
+
+ /**
+ * @constructor
+ * @param {HTMLElement} element The element that this component is connected to.
+ */
+ constructor(element) {
+ this.element_ = element;
+ this.init();
+ }
+
+ keyDownHandler = event => {
+ if (event.keyCode === VK_ENTER || event.keyCode === VK_SPACE) {
+ event.preventDefault();
+
+ // Trigger click
+ (event.target || this.controlElement).dispatchEvent(
+ new MouseEvent('click', {
+ bubbles: true,
+ cancelable: true,
+ view: window
+ })
+ );
+ }
+ };
+
+ clickHandler = event => {
+ if(!this.isDisabled) {
+ if(event.target !== this.controlElement) {
+ // Do not toggle if a focusable element inside the control element triggered the event
+ const p = getParentElements(event.target, this.controlElement);
+ p.push(event.target);
+ if(p.find( el => isFocusable(el))) {
+ return;
+ }
+ }
+ this.toggle();
+ }
+ };
+
+ get element() {
+ return this.element_;
+ }
+
+ get controlElement() {
+ return this.controlElement_;
+ }
+
+ get isDisabled() {
+ return (this.controlElement.hasAttribute('disabled') &&
+ this.controlElement.getAttribute('disabled').toLowerCase() !== 'false') ||
+ (this.controlElement.hasAttribute('aria-disabled') &&
+ this.controlElement.getAttribute('aria-disabled').toLowerCase() !== 'false');
+ }
+
+ get isExpanded() {
+ return this.controlElement.hasAttribute('aria-expanded') &&
+ this.controlElement.getAttribute('aria-expanded').toLowerCase() === 'true';
+ }
+
+ get regionIds() {
+ return this.controlElement.hasAttribute('aria-controls')
+ ? this.controlElement.getAttribute('aria-controls').split(' ')
+ : [];
+ }
+
+ get regionElements() {
+ return this.regionIds
+ .map(id => document.querySelector(`#${id}`))
+ .filter( el => el != null);
+ }
+
+ collapse() {
+ if(!this.isDisabled && this.isExpanded) {
+ if(this.dispatchToggleEvent('collapse')) {
+ this.controlElement.setAttribute('aria-expanded', 'false');
+ const regions = this.regionElements.slice(0);
+ for (let i = regions.length - 1; i >= 0; --i) {
+ regions[i].setAttribute('hidden', '');
+ }
+ }
+ }
+ }
+
+ expand() {
+ if(!this.isDisabled && !this.isExpanded) {
+ if(this.dispatchToggleEvent('expand')) {
+ this.controlElement.setAttribute('aria-expanded', 'true');
+ this.regionElements.forEach(region => region.removeAttribute('hidden'));
+ }
+ }
+ }
+
+ toggle() {
+ if (this.isExpanded) {
+ this.collapse();
+ }
+ else {
+ this.expand();
+ }
+ }
+
+ dispatchToggleEvent(action) {
+ return this.element.dispatchEvent(
+ new CustomEvent('toggle', {
+ bubbles: true,
+ cancelable: true,
+ detail: {
+ action: action
+ }
+ })
+ );
+ }
+
+ disableToggle() {
+ this.controlElement.setAttribute('aria-disabled', true);
+ }
+
+ enableToggle() {
+ this.controlElement.removeAttribute('aria-disabled');
+ }
+
+ addRegionId(regionId) {
+ const ids = this.regionIds;
+ if(!ids.find(id => regionId === id)) {
+ ids.push(regionId);
+ this.controlElement.setAttribute('aria-controls', ids.join(' '));
+ }
+ }
+
+ addRegionElement(region) {
+ if(!(region.classList.contains(COLLAPSIBLE_GROUP_CLASS) ||
+ region.classList.contains(COLLAPSIBLE_REGION_CLASS))) {
+ region.classList.add(COLLAPSIBLE_GROUP_CLASS);
+ }
+
+ if(!region.hasAttribute('role')) {
+ const role = region.classList.contains(COLLAPSIBLE_GROUP_CLASS) ? 'group' : 'region';
+ region.setAttribute('role', role);
+ }
+
+ if(!region.hasAttribute('id')) {
+ region.id = `${region.getAttribute('role')}-${randomString()}`;
+ }
+
+ if(this.isExpanded) {
+ region.removeAttribute('hidden');
+ }
+ else {
+ region.setAttribute('hidden', '');
+ }
+ this.addRegionId(region.id);
+ }
+
+ removeRegionElement(region) {
+ if(region && region.id) {
+ const ids = this.regionIds.filter(id => id === region.id);
+ this.controlElement.setAttribute('aria-controls', ids.join(' '));
+ }
+ }
+
+ removeListeners() {
+ this.controlElement.removeEventListener('keydown', this.keyDownHandler);
+ this.controlElement.removeEventListener('click', this.clickHandler);
+ }
+
+ init() {
+ const initControl = () => {
+ // Find the button element
+ this.controlElement_ = this.element.querySelector(`.${COLLAPSIBLE_CONTROL_CLASS}`) || this.element;
+
+ // Add "aria-expanded" attribute if not present
+ if(!this.controlElement.hasAttribute('aria-expanded')) {
+ this.controlElement.setAttribute('aria-expanded', 'false');
+ }
+
+ // Add role=button if control != <button>
+ if(this.controlElement.nodeName.toLowerCase() !== 'button') {
+ this.controlElement.setAttribute('role', 'button');
+ }
+
+ // Add tabindex
+ if(!isFocusable(this.controlElement) && !this.controlElement.hasAttribute('tabindex')) {
+ this.controlElement.setAttribute('tabindex', '0');
+ }
+ };
+
+ const initRegions = () => {
+ let regions = [];
+ if(!this.controlElement.hasAttribute('aria-controls')) {
+ // Add siblings as collapsible region(s)
+ let r = this.element.nextElementSibling;
+ while(r) {
+ if(r.classList.contains(COLLAPSIBLE_GROUP_CLASS) ||
+ r.classList.contains(COLLAPSIBLE_REGION_CLASS)) {
+ regions.push(r);
+ }
+ else if(r.classList.contains(JS_COLLAPSIBLE)) {
+ // A new collapsible component
+ break;
+ }
+ r = r.nextElementSibling;
+ }
+ }
+ else {
+ regions = this.regionElements;
+ }
+ regions.forEach(region => this.addRegionElement(region));
+ };
+
+ const addListeners = () => {
+ this.controlElement.addEventListener('keydown', this.keyDownHandler);
+ this.controlElement.addEventListener('click', this.clickHandler);
+ };
+
+ initControl();
+ initRegions();
+ this.removeListeners();
+ addListeners();
+ }
+
+ downgrade() {
+ this.removeListeners();
+ }
+
+}
+
+(function() {
+ 'use strict';
+
+ /**
+ * @constructor
+ * @param {HTMLElement} element The element that will be upgraded.
+ */
+ const MaterialExtCollapsible = function MaterialExtCollapsible(element) {
+ this.element_ = element;
+ this.collapsible = null;
+
+ // Initialize instance.
+ this.init();
+ };
+ window['MaterialExtCollapsible'] = MaterialExtCollapsible;
+
+ /**
+ * Initialize component
+ */
+ MaterialExtCollapsible.prototype.init = function() {
+ if (this.element_) {
+ this.collapsible = new Collapsible(this.element_);
+ this.element_.classList.add(IS_UPGRADED);
+
+ // Listen to 'mdl-componentdowngraded' event
+ this.element_.addEventListener('mdl-componentdowngraded', this.mdlDowngrade_.bind(this));
+ }
+ };
+
+ /*
+ * Downgrade component
+ * E.g remove listeners and clean up resources
+ */
+ MaterialExtCollapsible.prototype.mdlDowngrade_ = function() {
+ this.collapsible.downgrade();
+ };
+
+
+ // Public methods.
+
+ /**
+ * Get control element.
+ * @return {HTMLElement} element The element that controls the collapsible region.
+ * @public
+ */
+ MaterialExtCollapsible.prototype.getControlElement = function() {
+ return this.collapsible.controlElement;
+ };
+ MaterialExtCollapsible.prototype['getControlElement'] = MaterialExtCollapsible.prototype.getControlElement;
+
+ /**
+ * Get region elements controlled by this collapsible
+ * @returns {Array<HTMLElement>} the collapsible region elements
+ * @public
+ */
+ MaterialExtCollapsible.prototype.getRegionElements = function() {
+ return this.collapsible.regionElements;
+ };
+ MaterialExtCollapsible.prototype['getRegionElements'] = MaterialExtCollapsible.prototype.getRegionElements;
+
+ /**
+ * Add region elements.
+ * @param {Array<HTMLElement>} elements The element that will be upgraded.
+ * @return {void}
+ * @public
+ */
+ MaterialExtCollapsible.prototype.addRegionElements = function(...elements) {
+ elements.forEach(element => this.collapsible.addRegionElement(element));
+ };
+ MaterialExtCollapsible.prototype['addRegionElements'] = MaterialExtCollapsible.prototype.addRegionElements;
+
+ /**
+ * Remove collapsible region(s) from component.
+ * Note: This operation does not delete the element from the DOM tree.
+ * @param {Array<HTMLElement>} elements The element that will be upgraded.
+ * @public
+ */
+ MaterialExtCollapsible.prototype.removeRegionElements = function(...elements) {
+ elements.forEach(element => this.collapsible.removeRegionElement(element));
+ };
+ MaterialExtCollapsible.prototype['removeRegionElements'] = MaterialExtCollapsible.prototype.removeRegionElements;
+
+ /**
+ * Expand collapsible region(s)
+ * @return {void}
+ * @public
+ */
+ MaterialExtCollapsible.prototype.expand = function() {
+ this.collapsible.expand();
+ };
+ MaterialExtCollapsible.prototype['expand'] = MaterialExtCollapsible.prototype.expand;
+
+ /**
+ * Collapse collapsible region(s)
+ * @return {void}
+ * @public
+ */
+ MaterialExtCollapsible.prototype.collapse = function() {
+ this.collapsible.collapse();
+ };
+ MaterialExtCollapsible.prototype['collapse'] = MaterialExtCollapsible.prototype.collapse;
+
+ /**
+ * Toggle collapsible region(s)
+ * @return {void}
+ * @public
+ */
+ MaterialExtCollapsible.prototype.toggle = function() {
+ this.collapsible.toggle();
+ };
+ MaterialExtCollapsible.prototype['toggle'] = MaterialExtCollapsible.prototype.toggle;
+
+ /**
+ * Check whether component has aria-expanded state true
+ * @return {Boolean} true if aria-expanded="true", otherwise false
+ */
+ MaterialExtCollapsible.prototype.isExpanded = function() {
+ return this.collapsible.isExpanded;
+ };
+ MaterialExtCollapsible.prototype['isExpanded'] = MaterialExtCollapsible.prototype.isExpanded;
+
+ /**
+ * Check whether component has aria-disabled state set to true
+ * @return {Boolean} true if aria-disabled="true", otherwise false
+ */
+ MaterialExtCollapsible.prototype.isDisabled = function() {
+ return this.collapsible.isDisabled;
+ };
+ MaterialExtCollapsible.prototype['isDisabled'] = MaterialExtCollapsible.prototype.isDisabled;
+
+ /**
+ * Disables toggling of collapsible region(s)
+ * @return {void}
+ * @public
+ */
+ MaterialExtCollapsible.prototype.disableToggle = function() {
+ this.collapsible.disableToggle();
+ };
+ MaterialExtCollapsible.prototype['disableToggle'] = MaterialExtCollapsible.prototype.disableToggle;
+
+ /**
+ * Enables toggling of collapsible region(s)
+ * @return {void}
+ * @public
+ */
+ MaterialExtCollapsible.prototype.enableToggle = function() {
+ this.collapsible.enableToggle();
+ };
+ MaterialExtCollapsible.prototype['enableToggle'] = MaterialExtCollapsible.prototype.enableToggle;
+
+ // The component registers itself. It can assume componentHandler is available
+ // in the global scope.
+ /* eslint no-undef: 0 */
+ componentHandler.register({
+ constructor: MaterialExtCollapsible,
+ classAsString: 'MaterialExtCollapsible',
+ cssClass: JS_COLLAPSIBLE,
+ widget: true
+ });
+
+})();
diff --git a/node_modules/mdl-ext/src/collapsible/readme.md b/node_modules/mdl-ext/src/collapsible/readme.md
new file mode 100644
index 0000000..553e48a
--- /dev/null
+++ b/node_modules/mdl-ext/src/collapsible/readme.md
@@ -0,0 +1,467 @@
+# Collapsible
+
+**Collapsed**
+
+![Collapsible collapsed](../../etc/collapsible-collapsed.jpg)
+
+**Expanded**
+
+![Collapsible expanded](../../etc/collapsible-expanded.jpg)
+
+A collapsible is a component to mark expandable and collapsible regions. It has
+states, roles, attributes and behaviour in accordance with guidelines given in
+[Using the WAI-ARIA aria-expanded state to mark expandable and collapsible regions](https://www.w3.org/WAI/GL/wiki/Using_the_WAI-ARIA_aria-expanded_state_to_mark_expandable_and_collapsible_regions),
+[ARIA Authoring Practices, Button](https://www.w3.org/TR/wai-aria-practices-1.1/#button),
+and [Building Accessible Buttons with ARIA: A11y](http://www.deque.com/blog/accessible-aria-buttons/)
+
+## Collapse All the Things
+The collapsible acts as a "pluggable" component. It uses a `<button>` element or
+an element with `role="button"` to control one or more collapsible regions. You
+can make virtually any HTML element collapsible by adding two classes,
+`mdlext-js-collapsible` to the element that should control the collapsible
+region(s), and one of the classes `mdlext-collapsible-group` or
+`mdlext-collapsible-region` to the element that should collapse/expand. The
+collapsible component uses the
+[aria-controls](https://www.w3.org/TR/wai-aria/states_and_properties#aria-controls)
+property to hold a list of one or more collapsible regions. The
+[aria-expanded](https://www.w3.org/TR/wai-aria/states_and_properties#aria-expanded)
+state indicates whether region(s) controlled by the component is currently
+expanded or collapsed.
+
+## To include a MDLEXT collapsible component:
+ 1. Code a `<button>` element; this is the clickable toggle that will show and hide the collapsible
+region(s). Inside the button, code a `<span>` element to hold the button caption text.
+
+```html
+<button>
+ <span>Click to toggle</span>
+</button>
+```
+
+ 2. Add the `mdlext-js-collapsible` class to define the element as a collapsible component.
+
+```html
+<button class="mdlext-js-collapsible">
+ <span>Click to toggle</span>
+</button>
+```
+
+ 3. Optionally add the `mdlext-collapsible` class, which will add a pointer
+cursor to the collapsible component.
+
+```html
+<button class="mdlext-js-collapsible mdlext-collapsible">
+ <span>Click to toggle</span>
+</button>
+```
+
+ 4. Optionally add a state icon. Code a `<i>` element with class
+`mdlext-aria-expanded-more-less`. The state icon should indicate whether the
+collapsible region is expanded or not.
+
+```html
+<button class="mdlext-js-collapsible">
+ <span>Click to toggle</span>
+ <i class="mdlext-aria-expanded-more-less"></i>
+</button>
+```
+
+ 5. Code a `<div>` element with class `mdlext-collapsible-group` or
+`mdlext-collapsible-region` to define the element as a collapsible region.
+
+```html
+<div class="mdlext-collapsible-group">
+</div>
+```
+
+ 6. Add content inside the collapsible container.
+
+```html
+<div class="mdlext-collapsible-group">
+ <p>Content goes here ...</p>
+</div>
+```
+
+After page load, the component will add all required Aria states, roles and
+attributes not already present in markup.
+
+```html
+<button class="mdlext-js-collapsible is-upgraded"
+ data-upgraded=",MaterialExtCollapsible"
+ aria-expanded="false" aria-controls="group-4ek31z6jeeag">
+ <span>Click to toggle</span>
+ <i class="mdlext-aria-expanded-more-less"></i>
+</button>
+<div class="mdlext-collapsible-group" id="group-4ek31z6jeeag" role="group" hidden>
+ <p>Content goes here ...</p>
+</div>
+```
+
+Instead of letting the collapsible component add all the WAI-ARIA stuff,
+add it yourself in markup. The component will not override attributes already
+present in markup.
+
+```html
+<div class="mdlext-js-collapsible" role="button"
+ aria-expanded="false" aria-controls="group-1">
+ <span>Click to toggle</span>
+ <i class="mdlext-aria-expanded-more-less"></i>
+</div>
+<div class="mdlext-collapsible-group" id="group-1" role="group" hidden>
+ <p>Content Region #1 goes here ...</p>
+</div>
+```
+
+### role="group" vs role="region"
+The group role is used to identify a set of user interface objects which, in
+contrast with a region, are not intended to be included in a table of contents
+or a page summary (such as the structures that are dynamically created by a
+script or assistive technologies); a group should not be considered a major
+perceivable section on a page. When the role is added to an element, the browser
+will send out an accessible group event to assistive technology products which
+can then notify the user about it.
+
+To define an element as collapsible add one of the classes
+`mdlext-collapsible-group` or `mdlext-collapsible-region`. The component will
+set the role attribute to `group` or `region` accordingly.
+
+[Group](https://www.w3.org/TR/wai-aria/roles#group): A set of user interface
+objects which are not intended to be included in a page summary or table of
+contents by assistive technologies.
+
+[Region](https://www.w3.org/TR/wai-aria/roles#region): A large perceivable
+section of a web page or document, that is important enough to be included in a
+page summary or table of contents, for example, an area of the page containing
+live sporting event statistics.
+
+### Use a `<div>` element as a collapsible component.
+It's easier to style a div compared to a button. For example, you can not style
+a button as a flexible box!
+
+```html
+<div class="mdlext-js-collapsible mdlext-collapsible" aria-expanded="true">
+ <span>Click to toggle</span>
+ <i class="mdlext-aria-expanded-more-less"></i>
+</div>
+<div class="mdlext-collapsible-region">
+ <p>Content goes here ...</p>
+</div>
+```
+
+For further control with styling, it is possible to wrap the button element
+inside the collapsible component. The wrapped element becomes the clickable/focusable
+area and **must** have class `mdlext-collapsible` applied.
+
+```html
+<header class="mdlext-js-collapsible" aria-expanded="true">
+ <div class="mdlext-collapsible">
+ <span>Click to toggle</span>
+ <i class="mdlext-aria-expanded-more-less"></i>
+ </div>
+</header>
+<div class="mdlext-collapsible-region">
+ <p>Content goes here ...</p>
+</div>
+```
+
+### one-to-many
+You can create a one-to-many relationship by supplying a space separated list of
+ids, representing different, simultaneously controlled elements.
+
+```html
+<div class="medext-js-collapsible">
+ <div class="mdlext-collapsible" role="button"
+ aria-controls="collapsible-1 collapsible-3">A topic</div>
+</div>
+
+<div id="collapsible-1" class="mdlext-collapsible-group">
+ <p>Topic 1 is all about being Topic 1 and may or
+ may not have anything to do with other topics.</p>
+</div>
+
+<div id="collapsible-2" class="mdlext-collapsible-group">
+ <p>Topic 2 is all about being Topic 2 and may or
+ may not have anything to do with other topics.</p>
+</div>
+
+<div id="collapsible-3" class="mdlext-collapsible-group">
+ <p>Topic 3 is all about being Topic 3 and may or
+ may not have anything to do with other topics.</p>
+</div>
+```
+
+If the `aria-controls` attribute is provided in markup, the component will not
+attempt to determine corresponding collapsible regions. In the markup above,
+only `collapsible-1` and `collapsible-3` will be controlled by the component.
+
+Remove the `aria-controls` attribute if you want the component to determine the
+collapsible regions to be included.
+
+### Examples
+
+**Collapsibles, with many collapsible regions.**
+
+```html
+<!-- first collapsible -->
+<button class="mdlext-js-collapsible mdlext-collapsible">
+ <span>Click to toggle collapsible #1</span>
+ <i class="mdlext-aria-expanded-more-less"></i>
+</button>
+<div class="mdlext-collapsible-region">
+ <p>#1.1</p>
+</div>
+<div class="mdlext-collapsible-region">
+ <p>#1.2</p>
+</div>
+
+<!-- second collapsible -->
+<header class="mdlext-js-collapsible mdlext-collapsible">
+ <span>Click to toggle collapsible #2</span>
+ <i class="mdlext-aria-expanded-more-less"></i>
+</header>
+<div class="mdlext-collapsible-region">
+ <p>#2.1</p>
+</div>
+
+<p>This paragraph will not collapse</p>
+
+<div class="mdlext-collapsible-region">
+ <p>#2.2</p>
+</div>
+<div class="mdlext-collapsible-region">
+ <p>#2.3</p>
+</div>
+```
+
+**Nested collapsibles.**
+
+```html
+<style>
+ .mdlext-collapsible-region .mdlext-js-collapsible,
+ .mdlext-collapsible-region .mdlext-collapsible-region {
+ margin-left: 16px;
+ }
+</style>
+
+<button class="mdlext-js-collapsible mdl-button mdl-button--colored mdl-button--raised">
+ Click to toggle
+</button>
+<div class="mdlext-collapsible-region">
+ <p>A collapsible region</p>
+
+ <button class="mdlext-js-collapsible mdl-button mdl-button--accent mdl-button--raised">
+ Click to toggle nested #1
+ </button>
+ <div class="mdlext-collapsible-region">
+ <p>A nested collapsible region</p>
+
+ <button class="mdlext-js-collapsible mdl-button mdl-button--raised
+ mdl-button--colored mdl-color--deep-orange-100">
+ Click to toggle nested #2
+ </button>
+ <div class="mdlext-collapsible-region">
+ <p>Last region</p>
+ </div>
+ </div>
+</div>
+```
+
+**Collapsible MDL Card.**
+
+```html
+<!-- The card need some styling to act as a collapsible -->
+<style>
+ .mdl-card.welcome-card {
+ min-height: 0;
+ max-width: 640px;
+ width: auto;
+ }
+ .mdl-card.welcome-card > .mdl-card__title {
+ -webkit-box-pack: start;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ height: 176px;
+ min-height: 64px;
+ padding-top: 0;
+ padding-bottom: 0;
+ color: #fff;
+ background: url('./assets/welcome_card.jpg') top / cover;
+ }
+ .mdl-card.welcome-card .mdl-card__title:focus {
+ /* Must focus ring must be inside title since mdl-card has overflow:hidden */
+ outline-offset: -4px;
+ }
+ .mdl-card.welcome-card .mdl-card__title > * {
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center;
+ }
+ .mdl-card.welcome-card .mdl-card__supporting-text {
+ width: auto;
+ }
+ .mdl-card.welcome-card .mdl-card__actions {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ }
+ .welcome-card > .mdl-card__title .mdl-card__title-text {
+ -webkit-align-self: flex-end;
+ -ms-flex-item-align: end;
+ align-self: flex-end;
+ padding-bottom: 16px;
+ }
+ .welcome-card > .mdl-card__title[aria-expanded='false'] {
+ height: 64px;
+ }
+ .welcome-card > .mdl-card__title[aria-expanded='false'] .mdl-card__title-text {
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center;
+ padding-bottom: 0;
+ }
+ .welcome-card > .mdl-card__menu {
+ color: #ffffff;
+ }
+</style>
+
+<div class="welcome-card mdl-card mdl-shadow--2dp">
+ <header class="mdl-card__title mdlext-js-collapsible mdlext-collapsible">
+ <h2 class="mdl-card__title-text">A Collapsible Card</h2>
+ </header>
+ <section class="mdl-card__supporting-text mdlext-collapsible-region">
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ Mauris sagittis pellentesque lacus eleifend lacinia...
+ </section>
+ <footer class="mdl-card__actions mdl-card--border mdlext-collapsible-region">
+ <button class="mdl-button mdl-button--colored mdl-js-button mdl-js-ripple-effect">
+ Get Started
+ </button>
+ </footer>
+ <div class="mdl-card__menu">
+ <button class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
+ <i class="material-icons">share</i>
+ </button>
+ </div>
+</div>
+```
+
+**Create your own state icon with SASS.**
+
+The [_mixins.scss](../_mixins.scss) has a mixin which can be used to create custom state icons.
+
+```sass
+@charset "UTF-8";
+.my-aria-expanded-state {
+ @include mdlext-aria-expanded-toggle($icon: 'arrow_downward', $icon-expanded: 'arrow_upward');
+}
+```
+
+### More examples
+* The [snippets/collapsible.html](./snippets/collapsible.html) and the [tests](../../test/collapsible/collapsible.spec.js) provides more detailed examples.
+* Try out the [live demo](http://leifoolsen.github.io/mdl-ext/demo/collapsible.html)
+
+## Characteristics
+
+### Keyboard interaction
+* <kbd>Space</kbd> or <kbd>Enter</kbd>: toggle the corresponding collapsible region(s).
+
+### Mouse interaction
+* <kbd>Click</kbd>: toggle the corresponding collapsible region(s).
+
+## Events
+The collapsible component emits a custom `toggle` event when the component is clicked,
+<kbd>Enter</kbd> key or <kbd>Space</kbd> key is pressed or one of the methods `expand`.
+`collapse` or `toggle` is called. The event is emitted before the actual toggling
+occurs. Call `event.preventDefault()` to cancel toggling.
+
+The detail object parameter has the following structure:
+```javascript
+detail: {
+ action // 'expand' or collapse'
+}
+```
+Set up an event listener to receive the toggle event.
+```javascript
+var someCondition = false;
+document.querySelector('#my-collapsible').addEventListener('toggle', function(e) {
+ console.log('Toggle action:', e.detail.action);
+ if(someCondition) {
+ // Stop toggling
+ e.preventDefault();
+ }
+ someCondition = !someCondition;
+});
+```
+
+## Public methods
+
+### getControlElement()
+Get the element that controls the collapsible region(s).
+
+### getRegionElements()
+Get region elements controlled by this collapsible.
+
+### addRegionElements(...elements)
+Add collapsible region(s).
+
+### removeRegionElements(...elements)
+Remove collapsible region(s).
+
+### expand()
+Expand corresponding collapsible region(s).
+
+### collapse()
+Collapse corresponding collapsible region(s).
+
+### toggle()
+Toggle corresponding collapsible region(s).
+```javascript
+const component = document.querySelector('#my-collapsible');
+component.MaterialExtCollapsible.toggle();
+```
+### isExpanded()
+Check whether component has aria-expanded state set to true.
+
+### isDisabled()
+Check whether component has aria-disabled state set to true.
+
+### enableToggle()
+Enables toggling of collapsible region(s).
+
+### disableToggle()
+Disables toggling of collapsible region(s).
+
+## Configuration options
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements to the accordion.
+
+### Available classes and their effects.
+
+| MDLEXT class | Effect | Remarks |
+|--------------|--------|---------|
+|`mdlext-js-collapsible`| Assigns basic MDL behavior to collapsible. | Required. |
+|`mdlext-collapsible`| Defines container as an MDL component. | Optional. |
+|`mdlext-collapsible-group`| Defines container as a collapsible group. | Required. Either `mdlext-collapsible-group` or `mdlext-collapsible-region` must be present to make a container collapsible. |
+|`mdlext-collapsible-region`| Defines container as a collapsible region. | Required. |
+
+### Available WAI-ARIA roles, states, and properties
+
+| Attribute | Description | Remarks |
+|-----------|-------------|---------|
+|`role="button`| The element that toggles a region has role [button](http://www.w3.org/TR/wai-aria-1.1/#button). | Added by component if not present |
+|`tabindex`| Indicates whether an element is focusable. | A value less than 0, e.g. -1, indicates that the element is not focusable. Tabindex="0" added by component if not present |
+|`aria-controls`| Identfies the content on the page, using IDREFs, that this collapsible controls. | Added by component if not present. |
+|`aria-expanded`| The element with role `button` has [aria-expanded](https://www.w3.org/TR/wai-aria-1.1/#aria-expanded) set to `true` if the corresponding region(s) is open, oterwise false. | Defaults to `aria-expanded="false"`. Set `aria-expanded="true"` if you want a region to open during page load. |
+|`aria-disabled`| When a collapsible should not be toggable, set `aria-disabled` to `true`. | Optional. If this attribute is present, the collapsible region(s) will not toggle. |
+|`disabled`| Indicates that a collapsible component and it's corresponding region(s) is disabled, otherwise not present. | Optional. If this attribute is present, the collapsible regions will not toggle. |
+|`role="group`| Identifies an element as a collapsible [group](https://www.w3.org/TR/wai-aria/roles#group). | Required on container with class `mdlext-collapsible-group`. Added by component if not present. |
+|`role="region`| Identifies an element as a collapsible [region](https://www.w3.org/TR/wai-aria/roles#region). | Required on container with class `mdlext-collapsible-region`. Added by component if not present. |
+|`hidden`| Visually hides a collapsible region. | Added by component if component has `aria-expanded="false"`. |
+|`id`| The collapsible region must have an id. | A random id is added if not present. The IDREF is used by the `aria-controls` attribute to identify the collapsible region. |
+
+## Other collapsible examples
+* [ARIA Examples, Progressive collapsibles](http://heydonworks.com/practical_aria_examples/#progressive-collapsibles)
+* [Open Ajax, Example 20 - Hide/Show: Region follows button](http://oaa-accessibility.org/example/20/)
+* [Open Ajax, Example 21 - Hide/Show: Region does not follow button](http://oaa-accessibility.org/example/21/)
+* [Open Ajax, Example 22 - Hide/Show: Region is exclusive](http://oaa-accessibility.org/example/22/)
diff --git a/node_modules/mdl-ext/src/collapsible/snippets/collapsible.html b/node_modules/mdl-ext/src/collapsible/snippets/collapsible.html
new file mode 100644
index 0000000..f959654
--- /dev/null
+++ b/node_modules/mdl-ext/src/collapsible/snippets/collapsible.html
@@ -0,0 +1,237 @@
+<p>A collapsible is a component to mark expandable and collapsible regions.
+ It has states, roles, attributes and behavior in accordance with guidelines given in
+ <a href="https://www.w3.org/WAI/GL/wiki/Using_the_WAI-ARIA_aria-expanded_state_to_mark_expandable_and_collapsible_regions">
+ Using the WAI-ARIA aria-expanded state to mark expandable and collapsible regions
+ </a>.
+</p>
+<article>
+ <button class="mdlext-js-collapsible" style="padding: 8px;">
+ <span>Click to toggle (button)</span>
+ <i class="mdlext-aria-expanded-more-less"></i>
+ </button>
+ <div class="mdlext-collapsible-group"><p>A collapsible region #1.1</p></div>
+ <div class="mdlext-collapsible-group"><p>A collapsible region #1.2</p></div>
+ <div class="mdlext-collapsible-group"><p>A collapsible region #1.3</p></div>
+</article>
+
+<article style="margin-top: 16px;">
+ <div class="mdlext-js-collapsible mdlext-collapsible" style="padding: 8px;">
+ <span>Click to toggle (div)</span>
+ <i class="mdlext-aria-expanded-more-less"></i>
+ </div>
+ <div class="mdlext-collapsible-region"><p>A collapsible region #2.1</p></div>
+ <div class="mdlext-collapsible-region"><p>A collapsible region #2.2</p></div>
+ <div class="mdlext-collapsible-region"><p>A collapsible region #2.3</p></div>
+</article>
+
+
+<style>
+ .mdl-card.demo-card,
+ .mdl-card.welcome-card {
+ min-height: 0;
+ width: auto;
+ margin-top: 16px;
+ margin-bottom: 16px;
+ max-width: 640px;
+ }
+ .mdl-card.demo-card .mdl-card__media,
+ .mdl-card.welcome-card .mdl-card__media {
+ margin: 0;
+ text-align: center;
+ }
+ .mdl-card.demo-card .mdl-card__media > img,
+ .mdl-card.welcome-card .mdl-card__media > img {
+ max-width: 100%;
+ height: auto;
+ }
+ .mdl-card.demo-card .mdl-card__title,
+ .mdl-card.welcome-card .mdl-card__title {
+ /* Fix bug in _card.scss */
+ -webkit-box-pack: start;
+ -webkit-justify-content: flex-start;
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ /* end fix */
+
+ padding-top: 0;
+ padding-bottom: 0;
+ min-height: 64px;
+ }
+ .mdl-card.demo-card .mdl-card__title:focus,
+ .mdl-card.welcome-card .mdl-card__title:focus {
+ /* Must focus ring must be inside title since mdl-card has overflow:hidden */
+ outline-offset: -4px;
+ }
+ .mdl-card.demo-card .mdl-card__title > *,
+ .mdl-card.welcome-card .mdl-card__title > * {
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center;
+ }
+ .mdl-card.demo-card .mdl-card__supporting-text,
+ .mdl-card.welcome-card .mdl-card__supporting-text {
+ width: auto;
+ }
+ .mdl-card.demo-card .mdl-card__actions,
+ .mdl-card.welcome-card .mdl-card__actions {
+ display: -webkit-box;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: flex;
+ }
+ .welcome-card > .mdl-card__title {
+ color: #fff;
+ height: 176px;
+ background: url('./assets/welcome_card.jpg') top / cover;
+ }
+ .welcome-card > .mdl-card__title[aria-expanded='false'] {
+ height: 64px;
+ }
+ .welcome-card > .mdl-card__title .mdl-card__title-text {
+ -webkit-align-self: flex-end;
+ -ms-flex-item-align: end;
+ align-self: flex-end;
+ padding-bottom: 16px;
+ }
+ .welcome-card > .mdl-card__title[aria-expanded='false'] .mdl-card__title-text {
+ -webkit-align-self: center;
+ -ms-flex-item-align: center;
+ align-self: center;
+ padding-bottom: 0;
+ }
+ .welcome-card > .mdl-card__menu {
+ color: #fff;
+ }
+
+ table.info {
+ width: 100%
+ }
+ table.info th {
+ padding-right: 40px;
+ vertical-align: middle;
+ text-align: left;
+ width: 120px;
+ }
+</style>
+
+<div class="welcome-card mdl-card mdl-shadow--2dp">
+ <header class="mdl-card__title mdlext-js-collapsible mdlext-collapsible" aria-expanded="true">
+ <h2 class="mdl-card__title-text">A Collapsible Card</h2>
+ </header>
+ <section class="mdl-card__supporting-text mdlext-collapsible-group">
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ Mauris sagittis pellentesque lacus eleifend lacinia...
+ </section>
+ <footer class="mdl-card__actions mdl-card--border mdlext-collapsible-group">
+ <button class="mdl-button mdl-button--colored mdl-js-button mdl-js-ripple-effect">
+ Get Started
+ </button>
+ </footer>
+ <div class="mdl-card__menu">
+ <button class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
+ <i class="material-icons">share</i>
+ </button>
+ </div>
+</div>
+
+
+<style>
+ .mdlext-collapsible-group .mdlext-js-collapsible,
+ .mdlext-collapsible-group .mdlext-collapsible-group {
+ margin-left: 16px;
+ }
+</style>
+
+<button class="mdlext-js-collapsible mdl-button mdl-button--colored mdl-button--raised">Click to toggle</button>
+<div class="mdlext-collapsible-group">
+ <p>A collapsible region</p>
+
+ <button class="mdlext-js-collapsible mdl-button mdl-button--accent mdl-button--raised">Click to toggle nested #1</button>
+ <div class="mdlext-collapsible-group">
+ <p>A nested collapsible region</p>
+
+ <button class="mdlext-js-collapsible mdl-button mdl-button--colored mdl-color--deep-orange-100 mdl-button--raised">Click to toggle nested #2</button>
+ <div class="mdlext-collapsible-group">
+ <p>Last region</p>
+ </div>
+ </div>
+</div>
+
+
+<div id="another-card" class="mdl-card demo-card mdl-shadow--2dp mdlext-dark-color-theme">
+ <header class="mdl-card__title mdl-color--primary mdl-color-text--primary-contrast mdlext-js-collapsible mdlext-collapsible">
+ <button class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
+ <i class="material-icons">view_headline</i>
+ </button>
+ <h2 class="mdl-card__title-text">Another collapsible card</h2>
+ <div class="mdl-layout-spacer"></div>
+ <i class="material-icons md-36 mdlext-aria-expanded-more-less"></i>
+ </header>
+ <figure class="mdl-card__media mdlext-collapsible-region">
+ <img src="./images/_DSC7535-2.jpg" alt="">
+ </figure>
+ <section style="margin-top:16px" class="mdl-card__supporting-text mdlext-collapsible-region">
+ <table class="info">
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary-dark</th>
+ <td class="mdl-color--primary-dark mdl-color-text--primary-contrast">primary dark</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary</th>
+ <td class="mdl-color--primary mdl-color-text--primary-contrast">primary</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">accent</th>
+ <td class="mdl-color--accent mdl-color-text--accent-contrast">accent</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary-dark</th>
+ <td class="mdl-color--primary-contrast mdl-color-text--primary-dark">primary dark, inverted</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary</th>
+ <td class="mdl-color--primary-contrast mdl-color-text--primary">primary, inverted</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">accent</th>
+ <td class="mdl-color--accent-contrast mdl-color-text--accent">accent, inverted</td>
+ </tr>
+ </table>
+ </section>
+
+ <div class="mdl-card__supporting-text mdlext-collapsible-region">
+ Card Supporting Text
+ </div>
+
+ <footer class="mdl-card__actions mdl-card--border">
+ <button id="read-more" class="mdl-button mdl-button--colored mdl-js-button mdl-js-ripple-effect">
+ Read more
+ </button>
+ <div class="mdl-layout-spacer"></div>
+ <button class="mdl-button mdl-button--icon"><i class="material-icons">radio</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">favorite</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">share</i></button>
+ </footer>
+</div>
+
+
+
+<script>
+ (function() {
+ 'use strict';
+ window.addEventListener('load', function() {
+
+ document.querySelector('#read-more').addEventListener('click', function (e) {
+ var collapsible = document.querySelector('#another-card .mdlext-js-collapsible');
+ collapsible.MaterialExtCollapsible.expand();
+ });
+
+ document.querySelector('#another-card').addEventListener('toggle', function (e) {
+ console.log('Toggle action:', e.detail.action);
+ });
+
+ });
+
+ }());
+
+</script>
diff --git a/node_modules/mdl-ext/src/color-themes/_color-themes.scss b/node_modules/mdl-ext/src/color-themes/_color-themes.scss
new file mode 100644
index 0000000..6944941
--- /dev/null
+++ b/node_modules/mdl-ext/src/color-themes/_color-themes.scss
@@ -0,0 +1,57 @@
+/* -------------------------------------------------------------
+ Palette samples. Not part of build
+----------------------------------------------------------------
+
+$mdlext-light-color-primary: #9E9E9E !default;
+$mdlext-light-color-primary-dark: #616161 !default;
+$mdlext-light-color-primary-light: #9E9E9E !default; // Fallback color. Set to color-primary if fallback is not needed
+$mdlext-light-color-primary-contrast: #212121 !default; // text color on primary/primary dark background
+$mdlext-light-color-accent: #E040FB !default;
+$mdlext-light-color-accent-light: #E040FB !default; // Fallback color. Set to color-accent if fallback is not needed
+$mdlext-light-color-accent-contrast: #FAFAFA !default;
+
+$mdlext-light-color-primary: #F5F5F5 !default;
+$mdlext-light-color-primary-dark: #E0E0E0 !default;
+$mdlext-light-color-primary-light: #8BC34A !default; // Fallback color. Set to color-primary if fallback is not needed
+$mdlext-light-color-primary-contrast: #000000 !default; // text color on primary/primary dark background
+$mdlext-light-color-accent: #FFC107 !default;
+$mdlext-light-color-accent-light: #FFC107 !default; // Fallback color. Set to color-accent if fallback is not needed
+$mdlext-light-color-accent-contrast: #FFFFFF !default;
+
+
+$mdlext-light-color-primary: #673AB7 !default;
+$mdlext-light-color-primary-dark: #512DA8 !default;
+$mdlext-light-color-primary-light: #673AB7 !default; // Fallback color. Set to color-primary if fallback is not needed
+$mdlext-light-color-primary-contrast: #D1C4E9 !default; // text color on primary/primary dark background
+$mdlext-light-color-accent: #4CAF50 !default;
+$mdlext-light-color-accent-light: #4CAF50 !default; // Fallback color. Set to color-accent if fallback is not needed
+$mdlext-light-color-accent-contrast: #FFFFFF !default;
+
+
+$mdlext-light-color-primary: #4CAF50 !default;
+$mdlext-light-color-primary-dark: #388E3C !default;
+$mdlext-light-color-primary-light: #4CAF50 !default; // Fallback color. Set to color-primary if fallback is not needed
+$mdlext-light-color-primary-contrast: #C8E6C9 !default; // text color on primary/primary dark background
+$mdlext-light-color-accent: #FF5252 !default;
+$mdlext-light-color-accent-light: #FF5252 !default; // Fallback color. Set to color-accent if fallback is not needed
+$mdlext-light-color-accent-contrast: #FFFFFF !default;
+
+
+$mdlext-light-color-primary: #4CAF50 !default;
+$mdlext-light-color-primary-dark: #388E3C !default;
+$mdlext-light-color-primary-light: #4CAF50 !default; // Fallback color. Set to color-primary if fallback is not needed
+$mdlext-light-color-primary-contrast: #C8E6C9 !default; // text color on primary/primary dark background
+$mdlext-light-color-accent: #03A9F4 !default;
+$mdlext-light-color-accent-light: #03A9F4 !default; // Fallback color. Set to color-accent if fallback is not needed
+$mdlext-light-color-accent-contrast: #FFFFFF !default;
+
+
+$mdlext-dark-color-primary: #212121 !default;
+$mdlext-dark-color-primary-dark: #000000 !default;
+$mdlext-dark-color-primary-light: #607D8B !default; // Fallback color. Set to color-primary if fallback is not needed
+$mdlext-dark-color-primary-contrast: #FFFFFF !default; // text color on primary/primary dark background
+$mdlext-dark-color-accent: #FF5722 !default;
+$mdlext-dark-color-accent-light: #FF5722 !default; // Fallback color. Set to color-accent if fallback is not needed
+$mdlext-dark-color-accent-contrast: #FFFFFF !default;
+
+*/
diff --git a/node_modules/mdl-ext/src/color-themes/_dark-color-theme.scss b/node_modules/mdl-ext/src/color-themes/_dark-color-theme.scss
new file mode 100644
index 0000000..954e19c
--- /dev/null
+++ b/node_modules/mdl-ext/src/color-themes/_dark-color-theme.scss
@@ -0,0 +1,1132 @@
+@import "color-themes";
+
+.mdlext-dark-color-theme {
+ background-color: $mdlext-dark-content-background-color;
+ color: $mdlext-dark-text-color-primary;
+ a {
+ outline-color: inherit;
+ }
+}
+
+// mdl/src/palette/_palette.scss
+.mdlext-dark-color-theme {
+
+ .mdl-color--primary {
+ background-color: $mdlext-dark-color-primary !important;
+ }
+
+ .mdl-color--primary-contrast {
+ background-color: $mdlext-dark-color-primary-contrast !important;
+ }
+
+ .mdl-color--primary-dark {
+ background-color: $mdlext-dark-color-primary-dark !important;
+ }
+
+ .mdl-color--accent {
+ background-color: $mdlext-dark-color-accent !important;
+ }
+
+ .mdl-color--accent-contrast {
+ background-color: $mdlext-dark-color-accent-contrast !important;
+ }
+
+ .mdl-color-text--primary {
+ color: $mdlext-dark-color-primary !important;
+ }
+
+ .mdl-color-text--primary-contrast {
+ color: $mdlext-dark-color-primary-contrast !important;
+ }
+
+ .mdl-color-text--primary-dark {
+ color: $mdlext-dark-color-primary-dark !important;
+ }
+
+ .mdl-color-text--accent {
+ color: $mdlext-dark-color-accent !important;
+ }
+
+ .mdl-color-text--accent-contrast {
+ color: $mdlext-dark-color-accent-contrast !important;
+ }
+
+}
+
+// mdl/src/typography/_typography.scss
+.mdlext-dark-color-theme {
+ a {
+ color: $mdlext-dark-text-link-color;
+ }
+}
+
+
+// mdl/src/badge/_badge.scss
+// ---------------------------
+.mdlext-dark-color-theme {
+ .mdl-badge {
+
+ &[data-badge]::after {
+ background: $mdlext-dark-badge-background;
+ color: $mdlext-dark-badge-color;
+ }
+
+ &.mdl-badge--no-background {
+ &[data-badge]::after {
+ color: $mdlext-dark-badge-color-inverse;
+ background: $mdlext-dark-badge-background-inverse;
+ }
+ }
+ }
+}
+
+
+// mdl/src/button/_button.scss
+// ---------------------------
+.mdlext-dark-color-theme {
+
+ .mdl-button {
+ background: transparent;
+ color: $mdlext-dark-button-secondary-color;
+
+ &:hover {
+ background-color: $mdlext-dark-button-hover-color;
+ }
+
+ &:focus:not(:active) {
+ background-color: $mdlext-dark-button-focus-color;
+ }
+
+ &:active {
+ background-color: $mdlext-dark-button-active-color;
+ }
+
+ &.mdl-button--colored {
+ color: $mdlext-dark-button-primary-color-alt;
+
+ &:focus:not(:active) {
+ background-color: $mdlext-dark-button-focus-color-alt;
+ }
+ }
+ }
+
+ // Raised buttons
+ .mdl-button--raised {
+ background: $mdlext-dark-button-primary-color;
+
+ &:active {
+ background-color: $mdlext-dark-button-active-color;
+ }
+
+ &:focus:not(:active) {
+ background-color: $mdlext-dark-button-active-color;
+ }
+
+ &.mdl-button--colored {
+ background: $mdlext-dark-button-primary-color-alt;
+ color: $mdlext-dark-button-secondary-color-alt;
+
+ &:hover {
+ background-color: $mdlext-dark-button-hover-color-alt;
+ }
+
+ &:active {
+ background-color: $mdlext-dark-button-active-color-alt;
+ }
+
+ &:focus:not(:active) {
+ background-color: $mdlext-dark-button-active-color-alt;
+ }
+
+ & .mdl-ripple {
+ background: $mdlext-dark-button-ripple-color-alt;
+ }
+ }
+ }
+
+
+ // FABs
+ .mdl-button--fab {
+ background: $mdlext-dark-button-primary-color;
+
+ &:active {
+ background-color: $mdlext-dark-button-active-color;
+ }
+
+ &:focus:not(:active) {
+ background-color: $mdlext-dark-button-active-color;
+ }
+
+ &.mdl-button--colored {
+ background: $mdlext-dark-button-fab-color-alt;
+ color: $mdlext-dark-button-fab-text-color-alt;
+
+ &:hover {
+ background-color: $mdlext-dark-button-fab-hover-color-alt;
+ }
+
+ &:focus:not(:active) {
+ background-color: $mdlext-dark-button-fab-active-color-alt;
+ }
+
+ &:active {
+ background-color: $mdlext-dark-button-fab-active-color-alt;
+ }
+
+ & .mdl-ripple {
+ background: $mdlext-dark-button-fab-ripple-color-alt;
+ }
+ }
+ }
+
+
+ // Icon buttons
+ .mdl-button--icon {
+ color: inherit;
+ }
+
+ // Colorized buttons
+
+ .mdl-button--primary.mdl-button--primary {
+ color: $mdlext-dark-button-primary-color-alt;
+
+ & .mdl-ripple {
+ background: $mdlext-dark-button-secondary-color-alt;
+ }
+ &.mdl-button--raised,
+ &.mdl-button--fab {
+ color: $mdlext-dark-button-secondary-color-alt;
+ background-color: $mdlext-dark-button-primary-color-alt;
+ }
+ }
+
+ .mdl-button--accent.mdl-button--accent {
+ color: $mdlext-dark-button-fab-color-alt;
+
+ & .mdl-ripple {
+ background: $mdlext-dark-button-fab-text-color-alt;
+ }
+ &.mdl-button--raised,
+ &.mdl-button--fab {
+ color: $mdlext-dark-button-fab-text-color-alt;
+ background-color: $mdlext-dark-button-fab-color-alt;
+ }
+ }
+
+ // Disabled buttons
+
+ .mdl-button {
+ // Bump up specificity by using [disabled] twice.
+ &[disabled][disabled],
+ &.mdl-button--disabled.mdl-button--disabled {
+ color: $mdlext-dark-button-secondary-color-disabled;
+ background-color: transparent;
+ }
+
+ &--fab {
+ // Bump up specificity by using [disabled] twice.
+ &[disabled][disabled],
+ &.mdl-button--disabled.mdl-button--disabled {
+ background-color: $mdlext-dark-button-primary-color-disabled;
+ color: $mdlext-dark-button-secondary-color-disabled;
+ }
+ }
+
+ &--raised {
+ // Bump up specificity by using [disabled] twice.
+ &[disabled][disabled],
+ &.mdl-button--disabled.mdl-button--disabled {
+ background-color: $mdlext-dark-button-primary-color-disabled;
+ color: $mdlext-dark-button-secondary-color-disabled;
+ }
+ }
+ &--colored {
+ // Bump up specificity by using [disabled] twice.
+ &[disabled][disabled],
+ &.mdl-button--disabled.mdl-button--disabled {
+ color: $mdlext-dark-button-secondary-color-disabled;
+ }
+ }
+ }
+}
+
+
+// mdl/src/slider/_slider.scss
+// ---------------------------
+.mdlext-dark-color-theme {
+
+ .mdl-slider {
+
+ &.is-upgraded {
+ background: transparent;
+ color: $mdlext-dark-range-color;
+
+ &::-webkit-slider-runnable-track {
+ background: transparent;
+ }
+
+ &::-moz-range-track {
+ background: transparent;
+ }
+
+ &::-ms-track {
+ background: none;
+ color: transparent;
+ }
+
+ /* stylelint-disable */
+ &::-ms-fill-lower {
+ background: linear-gradient(
+ to right,
+ transparent,
+ transparent 16px,
+ $mdlext-dark-range-color 16px,
+ $mdlext-dark-range-color 0
+ );
+ }
+
+ &::-ms-fill-upper {
+ background: linear-gradient(
+ to left,
+ transparent,
+ transparent 16px,
+ $mdlext-dark-range-bg-color 16px,
+ $mdlext-dark-range-bg-color 0);
+ }
+ /* stylelint-enable */
+
+ &::-webkit-slider-thumb {
+ background: $mdlext-dark-range-color;
+ }
+
+ &::-moz-range-thumb {
+ background: $mdlext-dark-range-color;
+ }
+
+ &:focus:not(:active)::-webkit-slider-thumb {
+ box-shadow: 0 0 0 10px $mdlext-dark-range-faded-color;
+ }
+
+ &:focus:not(:active)::-moz-range-thumb {
+ box-shadow: 0 0 0 10px $mdlext-dark-range-faded-color;
+ }
+
+ &:active::-webkit-slider-thumb {
+ background: $mdlext-dark-range-color;
+ }
+
+ &:active::-moz-range-thumb {
+ background: $mdlext-dark-range-color;
+ }
+
+ &::-ms-thumb {
+ background: $mdlext-dark-range-color;
+ }
+
+ /* stylelint-disable */
+ &:focus:not(:active)::-ms-thumb {
+ background: radial-gradient(circle closest-side,
+ $mdlext-dark-range-color 0%,
+ $mdlext-dark-range-color 37.5%,
+ $mdlext-dark-range-faded-color 37.5%,
+ $mdlext-dark-range-faded-color 100%);
+ }
+ /* stylelint-enable */
+
+ &:active::-ms-thumb {
+ background: $mdlext-dark-range-color;
+ }
+
+
+ /**************************** 0-value ****************************/
+
+ &.is-lowest-value::-webkit-slider-thumb {
+ border-color: $mdlext-dark-range-color;
+ background: transparent;
+ }
+
+ &.is-lowest-value::-moz-range-thumb {
+ border-color: $mdlext-dark-range-bg-color;
+ background: transparent;
+ }
+
+ &.is-lowest-value:focus:not(:active)::-webkit-slider-thumb {
+ box-shadow: 0 0 0 10px $mdlext-dark-range-bg-focus-color;
+ background: $mdlext-dark-range-bg-focus-color;
+ }
+
+ &.is-lowest-value:focus:not(:active)::-moz-range-thumb {
+ box-shadow: 0 0 0 10px $mdlext-dark-range-bg-focus-color;
+ background: $mdlext-dark-range-bg-focus-color;
+ }
+
+ &.is-lowest-value:active::-webkit-slider-thumb {
+ border-color: $mdlext-dark-range-bg-color;
+ }
+
+ &.is-lowest-value:active::-moz-range-thumb {
+ border-color: $mdlext-dark-range-bg-color;
+ }
+
+ /* stylelint-disable */
+ &.is-lowest-value::-ms-thumb {
+ background: radial-gradient(circle closest-side,
+ transparent 0%,
+ transparent 66.67%,
+ $mdlext-dark-range-bg-color 66.67%,
+ $mdlext-dark-range-bg-color 100%);
+ }
+
+ &.is-lowest-value:focus:not(:active)::-ms-thumb {
+ background: radial-gradient(circle closest-side,
+ $mdlext-dark-range-bg-focus-color 0%,
+ $mdlext-dark-range-bg-focus-color 25%,
+ $mdlext-dark-range-bg-color 25%,
+ $mdlext-dark-range-bg-color 37.5%,
+ $mdlext-dark-range-bg-focus-color 37.5%,
+ $mdlext-dark-range-bg-focus-color 100%);
+ }
+
+ &.is-lowest-value:active::-ms-thumb {
+ background: radial-gradient(circle closest-side,
+ transparent 0%,
+ transparent 77.78%,
+ $mdlext-dark-range-bg-color 77.78%,
+ $mdlext-dark-range-bg-color 100%);
+ }
+ /* stylelint-enable */
+
+ &.is-lowest-value::-ms-fill-lower {
+ background: transparent;
+ }
+
+ /**************************** Disabled ****************************/
+
+ &:disabled:focus::-webkit-slider-thumb,
+ &:disabled:active::-webkit-slider-thumb,
+ &:disabled::-webkit-slider-thumb {
+ background: $mdlext-dark-range-bg-color;
+ }
+
+ &:disabled:focus::-moz-range-thumb,
+ &:disabled:active::-moz-range-thumb,
+ &:disabled::-moz-range-thumb {
+ background: $mdlext-dark-range-bg-color;
+ }
+
+ &:disabled + .mdl-slider__background-flex > .mdl-slider__background-lower {
+ background-color: $mdlext-dark-range-bg-color;
+ }
+
+ &.is-lowest-value:disabled:focus::-webkit-slider-thumb,
+ &.is-lowest-value:disabled:active::-webkit-slider-thumb,
+ &.is-lowest-value:disabled::-webkit-slider-thumb {
+ border-color: $mdlext-dark-range-bg-color;
+ background: transparent;
+ }
+
+ &.is-lowest-value:disabled:focus::-moz-range-thumb,
+ &.is-lowest-value:disabled:active::-moz-range-thumb,
+ &.is-lowest-value:disabled::-moz-range-thumb {
+ border-color: $mdlext-dark-range-bg-color;
+ background: transparent;
+ }
+
+ &:disabled:focus::-ms-thumb,
+ &:disabled:active::-ms-thumb,
+ &:disabled::-ms-thumb {
+ background: $mdlext-dark-range-bg-color;
+ }
+
+ /* stylelint-disable */
+ &.is-lowest-value:disabled:focus::-ms-thumb,
+ &.is-lowest-value:disabled:active::-ms-thumb,
+ &.is-lowest-value:disabled::-ms-thumb {
+ background: radial-gradient(circle closest-side,
+ transparent 0%,
+ transparent 50%,
+ $mdlext-dark-range-bg-color 50%,
+ $mdlext-dark-range-bg-color 100%);
+ }
+
+ &:disabled::-ms-fill-lower {
+ background: linear-gradient(to right,
+ transparent,
+ transparent 25px,
+ $mdlext-dark-range-bg-color 25px,
+ $mdlext-dark-range-bg-color 0);
+ }
+ /* stylelint-enable */
+
+ }
+ }
+
+ .mdl-slider__background-flex {
+ background: transparent;
+ }
+
+ .mdl-slider__background-lower {
+ background: $mdlext-dark-range-color;
+ }
+
+ // This one styles the upper part of the slider track.
+ .mdl-slider__background-upper {
+ background: $mdlext-dark-range-bg-color;
+ }
+}
+
+
+// mdl/src/textfield/_textfield.scss
+// -----------------------------------
+.mdlext-dark-color-theme {
+
+ .mdl-textfield__input {
+ border-bottom-color: $mdlext-dark-input-text-bottom-border-color;
+ }
+ .mdl-textfield.is-invalid .mdl-textfield__input {
+ border-color: $mdlext-dark-input-text-error-color;
+ }
+ fieldset[disabled] .mdl-textfield .mdl-textfield__input,
+ .mdl-textfield.is-disabled .mdl-textfield__input {
+ background-color: transparent;
+ border-bottom-color: $mdlext-dark-input-text-disabled-color;
+ color: $mdlext-dark-input-text-disabled-text-color;
+ }
+ .mdl-textfield__label {
+ color: $mdlext-dark-input-text-label-color;
+ }
+ .mdl-textfield__label::after {
+ background-color: $mdlext-dark-input-text-highlight-color;
+ }
+ fieldset[disabled] .mdl-textfield .mdl-textfield__label,
+ .mdl-textfield.is-disabled.is-disabled .mdl-textfield__label {
+ color: $mdlext-dark-input-text-disabled-text-color;
+ }
+ .mdl-textfield--floating-label.is-focused .mdl-textfield__label,
+ .mdl-textfield--floating-label.is-dirty .mdl-textfield__label,
+ .mdl-textfield--floating-label.has-placeholder .mdl-textfield__label {
+ color: $mdlext-dark-input-text-highlight-color;
+ }
+ .mdl-textfield--floating-label.is-invalid .mdl-textfield__label {
+ color: $mdlext-dark-input-text-error-color;
+ }
+ .mdl-textfield.is-invalid .mdl-textfield__label::after {
+ background-color: $mdlext-dark-input-text-error-color;
+ }
+ .mdl-textfield__error {
+ color: $mdlext-dark-input-text-error-color;
+ }
+}
+
+
+// mdl/src/checkbox/_checkbox.scss
+// -----------------------------------
+.mdlext-dark-color-theme {
+
+ .mdl-checkbox__box-outline {
+ border-color: $mdlext-dark-checkbox-off-color;
+ }
+ .mdl-checkbox.is-checked .mdl-checkbox__box-outline {
+ border-color: $mdlext-dark-checkbox-color;
+ }
+ fieldset[disabled] .mdl-checkbox .mdl-checkbox__box-outline,
+ .mdl-checkbox.is-disabled .mdl-checkbox__box-outline {
+ border-color: $mdlext-dark-checkbox-disabled-color;
+ }
+
+ .mdl-checkbox__focus-helper {
+ background-color: transparent;
+ }
+ .mdl-checkbox.is-focused.is-checked .mdl-checkbox__focus-helper {
+ box-shadow: 0 0 0 ($checkbox-button-size / 2) $mdlext-dark-checkbox-focus-color;
+ background-color: $mdlext-dark-checkbox-focus-color;
+ }
+
+ .mdl-checkbox__tick-outline {
+ background: transparent;
+ }
+ .mdl-checkbox.is-checked .mdl-checkbox__tick-outline {
+ background-color: $mdlext-dark-checkbox-color;
+ }
+ fieldset[disabled] .mdl-checkbox.is-checked .mdl-checkbox__tick-outline,
+ .mdl-checkbox.is-checked.is-disabled .mdl-checkbox__tick-outline {
+ background-color: $mdlext-dark-checkbox-disabled-color;
+ }
+
+ fieldset[disabled] .mdl-checkbox .mdl-checkbox__label,
+ .mdl-checkbox.is-disabled .mdl-checkbox__label {
+ color: $mdlext-dark-checkbox-disabled-color;
+ }
+
+ .mdl-checkbox__ripple-container .mdl-ripple {
+ background: $mdlext-dark-checkbox-color;
+ }
+ fieldset[disabled] .mdl-checkbox .mdl-checkbox__ripple-container .mdl-ripple,
+ .mdl-checkbox.is-disabled .mdl-checkbox__ripple-container .mdl-ripple {
+ background: transparent;
+ }
+
+}
+
+// mdl/src/radio/_radio.scss
+// -----------------------------------
+.mdlext-dark-color-theme {
+ .mdl-radio__outer-circle {
+ border-color: $mdlext-dark-radio-off-color;
+ }
+ .mdl-radio.is-checked .mdl-radio__outer-circle {
+ border-color: $mdlext-dark-radio-color;
+ }
+ .mdl-radio__outer-circle fieldset[disabled] .mdl-radio,
+ .mdl-radio.is-disabled .mdl-radio__outer-circle {
+ border-color: $mdlext-dark-radio-disabled-color;
+ }
+
+ .mdl-radio__inner-circle {
+ background: $mdlext-dark-radio-color;
+ }
+ fieldset[disabled] .mdl-radio .mdl-radio__inner-circle,
+ .mdl-radio.is-disabled .mdl-radio__inner-circle {
+ background: $mdlext-dark-radio-disabled-color;
+ }
+
+ fieldset[disabled] .mdl-radio .mdl-radio__label,
+ .mdl-radio.is-disabled .mdl-radio__label {
+ color: $mdlext-dark-radio-disabled-color;
+ }
+
+ .mdl-radio__ripple-container .mdl-ripple {
+ background: $mdlext-dark-radio-color;
+ }
+ fieldset[disabled] .mdl-radio .mdl-radio__ripple-container .mdl-ripple,
+ .mdl-radio.is-disabled .mdl-radio__ripple-container .mdl-ripple {
+ background: transparent;
+ }
+}
+
+// mdl/src/icon-togglr/_icon-toggle.scss
+// ---------------------------------------
+.mdlext-dark-color-theme {
+ .mdl-icon-toggle__label {
+ color: $mdlext-dark-icon-toggle-color;
+ }
+ .mdl-icon-toggle.is-checked .mdl-icon-toggle__label {
+ color: $mdlext-dark-icon-toggle-checked-color;
+ }
+ .mdl-icon-toggle.is-disabled .mdl-icon-toggle__label {
+ color: $mdlext-dark-icon-toggle-disabled-color;
+ }
+ .mdl-icon-toggle.is-focused .mdl-icon-toggle__label {
+ background-color: $mdlext-dark-icon-toggle-focus-color;
+ }
+ .mdl-icon-toggle.is-focused.is-checked .mdl-icon-toggle__label {
+ background-color: $mdlext-dark-icon-toggle-checked-focus-color;
+ }
+ .mdl-icon-toggle__ripple-container .mdl-ripple {
+ background: $mdlext-dark-icon-toggle-color;
+ }
+ .mdl-icon-toggle.is-disabled .mdl-icon-toggle__ripple-container .mdl-ripple {
+ background: transparent;
+ }
+}
+
+
+// mdl/src/switch/_switch.scss
+// -----------------------------------
+.mdlext-dark-color-theme {
+
+ .mdl-switch__track {
+ background: $mdlext-dark-switch-off-track-color;
+ }
+ .mdl-switch.is-checked .mdl-switch__track {
+ background: $mdlext-dark-switch-track-color;
+ }
+ .mdl-switch__track fieldset[disabled] .mdl-switch,
+ .mdl-switch.is-disabled .mdl-switch__track {
+ background: $mdlext-dark-switch-disabled-track-color;
+ }
+
+ .mdl-switch__thumb {
+ background: $mdlext-dark-switch-off-thumb-color;
+ }
+ .mdl-switch.is-checked .mdl-switch__thumb {
+ background: $mdlext-dark-switch-thumb-color;
+ }
+ .mdl-switch__thumb fieldset[disabled] .mdl-switch,
+ .mdl-switch.is-disabled .mdl-switch__thumb {
+ background: $mdlext-dark-switch-disabled-thumb-color;
+ }
+
+ .mdl-switch__focus-helper {
+ background-color: transparent;
+ }
+ .mdl-switch.is-focused .mdl-switch__focus-helper {
+ background-color: rgba(0, 0, 0, 0.1);
+ }
+ .mdl-switch.is-focused.is-checked .mdl-switch__focus-helper {
+ box-shadow: 0 0 0 (($switch-ripple-size - $switch-helper-size) / 2) $mdlext-dark-switch-faded-color;
+ background-color: $mdlext-dark-switch-faded-color;
+ }
+
+ .mdl-switch__label fieldset[disabled] .mdl-switch,
+ .mdl-switch.is-disabled .mdl-switch__label {
+ color: $mdlext-dark-switch-disabled-thumb-color;
+ }
+
+ .mdl-switch__ripple-container .mdl-ripple {
+ background: $mdlext-dark-switch-color;
+ }
+ fieldset[disabled] .mdl-switch .mdl-switch__ripple-container .mdl-ripple,
+ .mdl-switch.is-disabled .mdl-switch__ripple-container .mdl-ripple {
+ background: transparent;
+ }
+
+}
+
+
+// mdl/src/data-table/_data-table.scss
+// -----------------------------------
+.mdlext-dark-color-theme {
+
+ .mdl-data-table {
+ border-color: $mdlext-dark-data-table-divider-color;
+ background-color: $mdlext-dark-data-table-background-color;
+
+ tbody {
+ tr {
+ &.is-selected {
+ background-color: $mdlext-dark-data-table-selection-color;
+ }
+
+ &:hover {
+ background-color: $mdlext-dark-data-table-hover-color;
+ }
+ }
+ }
+
+ th {
+ color: $mdlext-dark-data-table-header-color;
+
+ &.mdl-data-table__header--sorted-ascending,
+ &.mdl-data-table__header--sorted-descending {
+ color: $mdlext-dark-data-table-header-sorted-color;
+
+ &:hover {
+ &::before {
+ color: $mdlext-dark-data-table-header-sorted-icon-hover-color;
+ }
+ }
+ }
+ }
+ }
+}
+
+// mdl/src/menu/_menu.scss
+// -----------------------------------
+.mdlext-dark-color-theme {
+
+ .mdl-menu__outline {
+ background: $mdlext-dark-default-dropdown-bg-color;
+ }
+
+ .mdl-menu__item {
+ color: $mdlext-dark-default-item-text-color;
+ background-color: transparent;
+ outline-color: $mdlext-dark-default-item-outline-color;
+
+ &--full-bleed-divider {
+ border-bottom-color: $mdlext-dark-default-item-divider-color;
+ }
+
+ &[disabled],
+ &[data-mdl-disabled] {
+ color: $mdlext-dark-disabled-item-text-color;
+ background-color: transparent;
+
+ &:hover {
+ background-color: transparent;
+ }
+
+ &:focus {
+ background-color: transparent;
+ }
+
+ & .mdl-ripple {
+ background: transparent;
+ }
+ }
+
+ &:hover {
+ background-color: $mdlext-dark-default-item-hover-bg-color;
+ }
+
+ &:focus {
+ background-color: $mdlext-dark-default-item-focus-bg-color;
+ }
+
+ &:active {
+ background-color: $mdlext-dark-default-item-active-bg-color;
+ }
+ }
+}
+
+// mdl/src/card/_card.scss
+// ----------------------------------------
+.mdlext-dark-color-theme {
+ .mdl-card {
+ background: $mdlext-dark-card-background-color;
+ }
+
+ .mdl-card__media {
+ background-color: $mdlext-dark-card-image-placeholder-color;
+ }
+
+ .mdl-card__title {
+ color: $mdlext-dark-card-text-color;
+
+ &.mdl-card--border {
+ border-bottom-color: $mdlext-dark-card-border-color;
+ }
+ }
+
+ .mdl-card__title-text {
+ color: inherit;
+ }
+
+ .mdl-card__subtitle-text {
+ color: $mdlext-dark-card-subtitle-color;
+ }
+
+ .mdl-card__supporting-text {
+ color: $mdlext-dark-card-supporting-text-text-color;
+ }
+
+ .mdl-card__actions {
+ background-color: rgba(255, 255, 255, 0);
+
+ &.mdl-card--border {
+ border-top-color: $mdlext-dark-card-border-color;
+ }
+ }
+}
+
+
+// mdlext/src/selectfield/_selectfield.scss
+// ----------------------------------------
+.mdlext-dark-color-theme {
+
+ .mdlext-selectfield.is-disabled::after {
+ color: $mdlext-dark-input-text-disabled-color;
+ @include mdlext-arrow(bottom, $mdlext-selectfield-arrow-width, $mdlext-selectfield-arrow-length, $mdlext-dark-input-text-disabled-color);
+ }
+
+ .mdlext-selectfield__select {
+ border-bottom-color: $mdlext-dark-input-text-bottom-border-color;
+ color: inherit;
+
+ option {
+ background-color: $mdlext-dark-content-background-color;
+ color: $mdlext-dark-text-color-primary;
+ }
+ }
+ .mdlext-selectfield.is-invalid .mdlext-selectfield__select {
+ border-color: $mdlext-dark-input-text-error-color;
+ }
+ fieldset[disabled] .mdlext-selectfield .mdlext-selectfield__select,
+ .mdlext-selectfield.is-disabled .mdlext-selectfield__select {
+ background-color: transparent;
+ border-bottom-color: $mdlext-dark-input-text-disabled-color;
+ color: $mdlext-dark-input-text-disabled-text-color;
+ }
+
+ .mdlext-selectfield__label {
+ color: $mdlext-dark-input-text-label-color;
+ }
+ fieldset[disabled] .mdlext-selectfield .mdlext-selectfield__label,
+ .mdlext-selectfield.is-disabled.is-disabled .mdlext-selectfield__label {
+ color: $mdlext-dark-input-text-disabled-text-color;
+ }
+ .mdlext-selectfield--floating-label.is-focused .mdlext-selectfield__label,
+ .mdlext-selectfield--floating-label.is-dirty .mdlext-selectfield__label,
+ .mdlext-selectfield--floating-label.is-dirty.is-dirty .mdlext-selectfield__label,
+ .mdlext-selectfield--floating-label.has-placeholder .mdlext-selectfield__label {
+ color: $mdlext-dark-input-text-highlight-color;
+ }
+ .mdlext-selectfield--floating-label.is-invalid .mdlext-selectfield__label {
+ color: $mdlext-dark-input-text-error-color;
+ }
+ .mdlext-selectfield__label::after {
+ background-color: $mdlext-dark-input-text-highlight-color;
+ }
+ .mdlext-selectfield.is-invalid .mdlext-selectfield__label::after {
+ background-color: $mdlext-dark-input-text-error-color;
+ }
+
+ .mdlext-selectfield__error {
+ color: $mdlext-dark-input-text-error-color;
+ }
+}
+
+
+// mdlext/src/menu-button/_menu-button.scss
+// ----------------------------------------
+.mdlext-menu.mdlext-dark-color-theme {
+ background: $mdlext-dark-default-dropdown-bg-color;
+}
+
+.mdlext-dark-color-theme {
+
+ .mdlext-menu {
+ background: $mdlext-dark-default-dropdown-bg-color;
+
+ &__item {
+ color: $mdlext-dark-default-item-text-color;
+ background-color: $mdlext-dark-default-dropdown-bg-color;
+
+ &:active,
+ &[aria-selected='true'] {
+ background-color: $mdlext-dark-default-item-active-bg-color;
+ }
+ &:hover:not([disabled]) {
+ background-color: $mdlext-dark-default-item-hover-bg-color;
+ }
+ &:focus {
+ outline-color: $mdlext-dark-default-item-outline-color;
+ background-color: $mdlext-dark-default-item-focus-bg-color;
+ }
+ &[disabled] {
+ color: $mdlext-dark-disabled-item-text-color;
+
+ > * {
+ color: $mdlext-dark-disabled-item-text-color;
+ }
+ }
+ }
+ &__item-separator {
+ border-bottom: 1px solid $mdlext-dark-default-item-divider-color;
+ }
+ }
+}
+
+
+// mdlext/src/bordered-fields/_bordered-fields.scss
+// -------------------------------------------------
+.mdlext-dark-color-theme {
+
+ .mdlext-bordered-fields {
+
+ .mdl-textfield,
+ .mdlext-selectfield {
+
+ .mdl-textfield__input,
+ .mdlext-selectfield__select {
+ background-color: $mdlext-dark-bordered-field-background-color;
+ border-color: $mdlext-dark-bordered-field-border-color;
+ color: $mdlext-dark-bordered-field-input-text-color;
+
+ &:disabled {
+ color: $mdlext-dark-bordered-field-input-text-disabled-text-color;
+ background-color: $mdlext-dark-bordered-field-disabled-background-color;
+ border-color: $mdlext-dark-bordered-field-disabled-border-color;
+ }
+ &:focus {
+ background-color: $mdlext-dark-bordered-field-focus-background-color;
+ border-color: $mdlext-dark-bordered-field-focus-border-color;
+ }
+ }
+ &.is-invalid {
+ .mdl-textfield__input,
+ .mdlext-selectfield__select {
+ color: $mdlext-dark-bordered-field-input-text-error-color;
+ border-color: $mdlext-dark-bordered-field-error-border-color;
+ background-color: $mdlext-dark-bordered-field-error-background-color;
+
+ &:focus {
+ border-color: $mdlext-dark-bordered-field-error-focus-border-color;
+ background-color: $mdlext-dark-bordered-field-error-focus-background-color;
+ }
+ }
+ }
+ }
+
+ fieldset[disabled] .mdlext-selectfield::after,
+ .mdlext-selectfield.is-disabled::after {
+ color: $mdlext-dark-bordered-field-input-text-disabled-text-color;
+ @include mdlext-arrow(bottom, $mdlext-selectfield-arrow-width, $mdlext-selectfield-arrow-length, $mdlext-dark-bordered-field-input-text-disabled-text-color);
+ }
+
+ fieldset[disabled] .mdl-textfield .mdl-textfield__input,
+ fieldset[disabled] .mdlext-selectfield .mdlext-selectfield__select {
+ color: $mdlext-dark-bordered-field-input-text-disabled-text-color;
+ background-color: $mdlext-dark-bordered-field-disabled-background-color;
+ border-color: $mdlext-dark-bordered-field-disabled-border-color;
+ }
+
+ .mdl-textfield,
+ .mdlext-selectfield {
+
+ .mdl-textfield__label,
+ .mdlext-selectfield__label {
+ color: $mdlext-dark-bordered-field-input-text-label-color;
+ }
+ &.mdl-textfield--floating-label.is-focused.is-focused,
+ &.mdl-textfield--floating-label.is-dirty.is-dirty,
+ &.mdl-textfield--floating-label.has-placeholder,
+ &.mdlext-selectfield--floating-label.is-focused.is-focused,
+ &.mdlext-selectfield--floating-label.is-dirty.is-dirty,
+ &.mdlext-selectfield--floating-label.has-placeholder {
+
+ .mdl-textfield__label,
+ .mdlext-selectfield__label {
+ color: $mdlext-dark-bordered-field-input-text-label-focus-color;
+ }
+ }
+ &.mdl-textfield--floating-label.is-disabled.is-disabled,
+ &.mdlext-selectfield--floating-label.is-disabled.is-disabled {
+
+ .mdl-textfield__label,
+ .mdlext-selectfield__label {
+ color: $mdlext-dark-bordered-field-input-text-label-disabled-color;
+ }
+ }
+ &.mdl-textfield--floating-label.is-invalid.is-invalid,
+ &.mdlext-selectfield--floating-label.is-invalid.is-invalid {
+
+ .mdl-textfield__label,
+ .mdlext-selectfield__label {
+ color: $mdlext-dark-bordered-field-input-text-label-error-color;
+ }
+ }
+ }
+
+ fieldset[disabled] .mdl-textfield .mdl-textfield__label,
+ fieldset[disabled] .mdl-selectfield .mdl-selectfield__label {
+ color: $mdlext-dark-bordered-field-input-text-label-disabled-color;
+ }
+
+ // Icon(s) and/or button(s) inside textfield
+ .mdl-textfield,
+ .mdlext-selectfield {
+ &.is-disabled i,
+ &.is-disabled .mdl-button {
+ color: $mdlext-dark-bordered-field-disabled-border-color;
+ }
+ }
+ fieldset[disabled] .mdl-textfield,
+ fieldset[disabled] .mdlext-selectfield {
+ i,
+ .mdl-button {
+ color: $mdlext-dark-bordered-field-disabled-border-color;
+ }
+ }
+ }
+
+}
+
+
+// mdlext/src/accordion/_accordion.scss
+// ----------------------------------------
+.mdlext-dark-color-theme {
+
+ .mdlext-accordion {
+
+ &__tab {
+ color: $mdlext-dark-accordion-header-secondary-color;
+ background-color: $mdlext-dark-accordion-header-background-color;
+
+ &:focus {
+ outline-color: $mdlext-dark-accordion-header-focus-outline-color;
+ }
+ &[aria-expanded='true'] {
+ background-color: $mdlext-dark-accordion-header-background-open-color;
+ }
+ &[aria-selected='true'] {
+ background-color: $mdlext-dark-accordion-header-background-active-color;
+ }
+ &[disabled] {
+ background-color: $mdlext-dark-accordion-header-disabled-color;
+ color: $mdlext-dark-accordion-header-secondary-color-disabled;
+ pointer-events: none;
+
+ > * {
+ color: $mdlext-dark-accordion-header-secondary-color-disabled;
+ }
+ }
+ &:hover:not([disabled]) {
+ background-color: $mdlext-dark-accordion-header-background-hover-color;
+ }
+ &--ripple {
+ &[aria-selected='true']::before {
+ background: $mdlext-dark-accordion-ripple-color;
+ }
+ }
+ }
+
+ &__tabpanel {
+ color: $mdlext-dark-accordion-content-color;
+ background-color: $mdlext-dark-accordion-content-background-color;
+ }
+ }
+
+ // Vertical layout
+ .mdlext-accordion {
+
+ &--vertical {
+
+ .mdlext-accordion__tab {
+ border-top: 1px solid $mdlext-dark-accordion-header-border-color;
+
+ &[aria-selected='true']::after {
+ background-color: $mdlext-dark-accordion-header-highlight-color;
+ }
+ }
+ .mdlext-accordion__tabpanel {
+ border-top: 1px solid $mdlext-dark-accordion-header-border-color;
+ }
+ }
+ }
+
+ // Horizontal layout
+ .mdlext-accordion {
+
+ &--horizontal {
+
+ .mdlext-accordion__tab {
+ border-left: 1px solid $mdlext-dark-accordion-header-border-color;
+
+ &[aria-selected='true']::after {
+ background-color: $mdlext-dark-accordion-header-highlight-color;
+ }
+ }
+ .mdlext-accordion__tabpanel {
+ border-left: 1px solid $mdlext-dark-accordion-header-border-color;
+ }
+ }
+ }
+
+ .mdlext-accordion {
+
+ &__panel:first-child > &__tab {
+ // Use container to set outer borders
+ border-top-color: transparent;
+ border-left-color: transparent;
+ }
+ }
+
+ // Making accordion appear disabled.
+ // Note: does not prevent tabbing into a disabled accordion
+ .mdlext-accordion[disabled] {
+ .mdlext-accordion__tab {
+ background-color: $mdlext-dark-accordion-header-disabled-color;
+ color: $mdlext-dark-accordion-header-secondary-color-disabled;
+
+ > * {
+ color: $mdlext-dark-accordion-header-secondary-color-disabled;
+ }
+ }
+ .mdlext-accordion__tabpanel {
+ opacity: 0.8;
+ filter: blur(1px) grayscale(80%);
+ }
+ }
+}
diff --git a/node_modules/mdl-ext/src/color-themes/_light-color-theme.scss b/node_modules/mdl-ext/src/color-themes/_light-color-theme.scss
new file mode 100644
index 0000000..5393738
--- /dev/null
+++ b/node_modules/mdl-ext/src/color-themes/_light-color-theme.scss
@@ -0,0 +1,1130 @@
+@import "color-themes";
+
+.mdlext-light-color-theme {
+ background-color: $mdlext-light-content-background-color;
+ color: $mdlext-light-text-color-primary;
+
+ a {
+ outline-color: inherit;
+ }
+}
+
+// mdl/src/palette/_palette.scss
+// -----------------------------
+.mdlext-light-color-theme {
+
+ .mdl-color--primary {
+ background-color: $mdlext-light-color-primary !important;
+ }
+
+ .mdl-color--primary-contrast {
+ background-color: $mdlext-light-color-primary-contrast !important;
+ }
+
+ .mdl-color--primary-dark {
+ background-color: $mdlext-light-color-primary-dark !important;
+ }
+
+ .mdl-color--accent {
+ background-color: $mdlext-light-color-accent !important;
+ }
+
+ .mdl-color--accent-contrast {
+ background-color: $mdlext-light-color-accent-contrast !important;
+ }
+
+ .mdl-color-text--primary {
+ color: $mdlext-light-color-primary !important;
+ }
+
+ .mdl-color-text--primary-contrast {
+ color: $mdlext-light-color-primary-contrast !important;
+ }
+
+ .mdl-color-text--primary-dark {
+ color: $mdlext-light-color-primary-dark !important;
+ }
+
+ .mdl-color-text--accent {
+ color: $mdlext-light-color-accent !important;
+ }
+
+ .mdl-color-text--accent-contrast {
+ color: $mdlext-light-color-accent-contrast !important;
+ }
+
+}
+
+// mdl/src/typography/_typography.scss
+// -----------------------------------
+.mdlext-light-color-theme {
+ a {
+ color: $mdlext-light-text-link-color;
+ }
+}
+
+
+// mdl/src/badge/_badge.scss
+// ---------------------------
+.mdlext-light-color-theme {
+ .mdl-badge {
+
+ &[data-badge]::after {
+ background: $mdlext-light-badge-background;
+ color: $mdlext-light-badge-color;
+ }
+
+ &.mdl-badge--no-background {
+ &[data-badge]::after {
+ color: $mdlext-light-badge-color-inverse;
+ background: $mdlext-light-badge-background-inverse;
+ }
+ }
+ }
+}
+
+
+// mdl/src/button/_button.scss
+// ---------------------------
+.mdlext-light-color-theme {
+
+ .mdl-button {
+ background: transparent;
+ color: $mdlext-light-button-secondary-color;
+
+ &:hover {
+ background-color: $mdlext-light-button-hover-color;
+ }
+
+ &:focus:not(:active) {
+ background-color: $mdlext-light-button-focus-color;
+ }
+
+ &:active {
+ background-color: $mdlext-light-button-active-color;
+ }
+
+ &.mdl-button--colored {
+ color: $mdlext-light-button-primary-color-alt;
+
+ &:focus:not(:active) {
+ background-color: $mdlext-light-button-focus-color-alt;
+ }
+ }
+ }
+
+ // Raised buttons
+ .mdl-button--raised {
+ background: $mdlext-light-button-primary-color;
+
+ &:active {
+ background-color: $mdlext-light-button-active-color;
+ }
+
+ &:focus:not(:active) {
+ background-color: $mdlext-light-button-active-color;
+ }
+
+ &.mdl-button--colored {
+ background: $mdlext-light-button-primary-color-alt;
+ color: $mdlext-light-button-secondary-color-alt;
+
+ &:hover {
+ background-color: $mdlext-light-button-hover-color-alt;
+ }
+
+ &:active {
+ background-color: $mdlext-light-button-active-color-alt;
+ }
+
+ &:focus:not(:active) {
+ background-color: $mdlext-light-button-active-color-alt;
+ }
+
+ & .mdl-ripple {
+ background: $mdlext-light-button-ripple-color-alt;
+ }
+ }
+ }
+
+
+ // FABs
+ .mdl-button--fab {
+ background: $mdlext-light-button-primary-color;
+
+ &:active {
+ background-color: $mdlext-light-button-active-color;
+ }
+
+ &:focus:not(:active) {
+ background-color: $mdlext-light-button-active-color;
+ }
+
+ &.mdl-button--colored {
+ background: $mdlext-light-button-fab-color-alt;
+ color: $mdlext-light-button-fab-text-color-alt;
+
+ &:hover {
+ background-color: $mdlext-light-button-fab-hover-color-alt;
+ }
+
+ &:focus:not(:active) {
+ background-color: $mdlext-light-button-fab-active-color-alt;
+ }
+
+ &:active {
+ background-color: $mdlext-light-button-fab-active-color-alt;
+ }
+
+ & .mdl-ripple {
+ background: $mdlext-light-button-fab-ripple-color-alt;
+ }
+ }
+ }
+
+
+ // Icon buttons
+ .mdl-button--icon {
+ color: inherit;
+ }
+
+ // Colorized buttons
+
+ .mdl-button--primary.mdl-button--primary {
+ color: $mdlext-light-button-primary-color-alt;
+
+ & .mdl-ripple {
+ background: $mdlext-light-button-secondary-color-alt;
+ }
+ &.mdl-button--raised,
+ &.mdl-button--fab {
+ color: $mdlext-light-button-secondary-color-alt;
+ background-color: $mdlext-light-button-primary-color-alt;
+ }
+ }
+
+ .mdl-button--accent.mdl-button--accent {
+ color: $mdlext-light-button-fab-color-alt;
+
+ & .mdl-ripple {
+ background: $mdlext-light-button-fab-text-color-alt;
+ }
+ &.mdl-button--raised,
+ &.mdl-button--fab {
+ color: $mdlext-light-button-fab-text-color-alt;
+ background-color: $mdlext-light-button-fab-color-alt;
+ }
+ }
+
+ // Disabled buttons
+
+ .mdl-button {
+ // Bump up specificity by using [disabled] twice.
+ &[disabled][disabled],
+ &.mdl-button--disabled.mdl-button--disabled {
+ color: $mdlext-light-button-secondary-color-disabled;
+ background-color: transparent;
+ }
+
+ &--fab {
+ // Bump up specificity by using [disabled] twice.
+ &[disabled][disabled],
+ &.mdl-button--disabled.mdl-button--disabled {
+ background-color: $mdlext-light-button-primary-color-disabled;
+ color: $mdlext-light-button-secondary-color-disabled;
+ }
+ }
+
+ &--raised {
+ // Bump up specificity by using [disabled] twice.
+ &[disabled][disabled],
+ &.mdl-button--disabled.mdl-button--disabled {
+ background-color: $mdlext-light-button-primary-color-disabled;
+ color: $mdlext-light-button-secondary-color-disabled;
+ }
+ }
+ &--colored {
+ // Bump up specificity by using [disabled] twice.
+ &[disabled][disabled],
+ &.mdl-button--disabled.mdl-button--disabled {
+ color: $mdlext-light-button-secondary-color-disabled;
+ }
+ }
+ }
+}
+
+// mdl/src/slider/_slider.scss
+// ---------------------------
+.mdlext-light-color-theme {
+ .mdl-slider {
+
+ &.is-upgraded {
+ background: transparent;
+ color: $mdlext-light-range-color;
+
+ &::-webkit-slider-runnable-track {
+ background: transparent;
+ }
+
+ &::-moz-range-track {
+ background: transparent;
+ }
+
+ &::-ms-track {
+ background: none;
+ color: transparent;
+ }
+
+ /* stylelint-disable */
+ &::-ms-fill-lower {
+ background: linear-gradient(to right,
+ transparent,
+ transparent 16px,
+ $mdlext-light-range-color 16px,
+ $mdlext-light-range-color 0);
+ }
+
+ &::-ms-fill-upper {
+ background: linear-gradient(to left,
+ transparent,
+ transparent 16px,
+ $mdlext-light-range-bg-color 16px,
+ $mdlext-light-range-bg-color 0);
+ }
+ /* stylelint-enable */
+
+
+ /**************************** Thumbs ****************************/
+ &::-webkit-slider-thumb {
+ background: $mdlext-light-range-color;
+ }
+
+ &::-moz-range-thumb {
+ background: $mdlext-light-range-color;
+ }
+
+ &:focus:not(:active)::-webkit-slider-thumb {
+ box-shadow: 0 0 0 10px $mdlext-light-range-faded-color;
+ }
+
+ &:focus:not(:active)::-moz-range-thumb {
+ box-shadow: 0 0 0 10px $mdlext-light-range-faded-color;
+ }
+
+ &:active::-webkit-slider-thumb {
+ background: $mdlext-light-range-color;
+ }
+
+ &:active::-moz-range-thumb {
+ background: $mdlext-light-range-color;
+ }
+
+ &::-ms-thumb {
+ background: $mdlext-light-range-color;
+ }
+
+ /* stylelint-disable */
+ &:focus:not(:active)::-ms-thumb {
+ background: radial-gradient(circle closest-side,
+ $mdlext-light-range-color 0%,
+ $mdlext-light-range-color 37.5%,
+ $mdlext-light-range-faded-color 37.5%,
+ $mdlext-light-range-faded-color 100%);
+ }
+ /* stylelint-enable */
+
+ &:active::-ms-thumb {
+ background: $mdlext-light-range-color;
+ }
+
+
+ /**************************** 0-value ****************************/
+
+ &.is-lowest-value::-webkit-slider-thumb {
+ border-color: $mdlext-light-range-color;
+ background: transparent;
+ }
+
+ &.is-lowest-value::-moz-range-thumb {
+ border-color: $mdlext-light-range-bg-color;
+ background: transparent;
+ }
+
+ &.is-lowest-value:focus:not(:active)::-webkit-slider-thumb {
+ box-shadow: 0 0 0 10px $mdlext-light-range-bg-focus-color;
+ background: $mdlext-light-range-bg-focus-color;
+ }
+
+ &.is-lowest-value:focus:not(:active)::-moz-range-thumb {
+ box-shadow: 0 0 0 10px $mdlext-light-range-bg-focus-color;
+ background: $mdlext-light-range-bg-focus-color;
+ }
+
+ &.is-lowest-value:active::-webkit-slider-thumb {
+ border-color: $mdlext-light-range-bg-color;
+ }
+
+ &.is-lowest-value:active::-moz-range-thumb {
+ border-color: $mdlext-light-range-bg-color;
+ }
+
+ /* stylelint-disable */
+ &.is-lowest-value::-ms-thumb {
+ background: radial-gradient(circle closest-side,
+ transparent 0%,
+ transparent 66.67%,
+ $mdlext-light-range-bg-color 66.67%,
+ $mdlext-light-range-bg-color 100%);
+ }
+
+ &.is-lowest-value:focus:not(:active)::-ms-thumb {
+ background: radial-gradient(circle closest-side,
+ $mdlext-light-range-bg-focus-color 0%,
+ $mdlext-light-range-bg-focus-color 25%,
+ $mdlext-light-range-bg-color 25%,
+ $mdlext-light-range-bg-color 37.5%,
+ $mdlext-light-range-bg-focus-color 37.5%,
+ $mdlext-light-range-bg-focus-color 100%);
+ }
+
+ &.is-lowest-value:active::-ms-thumb {
+ background: radial-gradient(circle closest-side,
+ transparent 0%,
+ transparent 77.78%,
+ $mdlext-light-range-bg-color 77.78%,
+ $mdlext-light-range-bg-color 100%);
+ }
+ /* stylelint-enable */
+
+ &.is-lowest-value::-ms-fill-lower {
+ background: transparent;
+ }
+
+ /**************************** Disabled ****************************/
+
+ &:disabled:focus::-webkit-slider-thumb,
+ &:disabled:active::-webkit-slider-thumb,
+ &:disabled::-webkit-slider-thumb {
+ background: $mdlext-light-range-bg-color;
+ }
+
+ &:disabled:focus::-moz-range-thumb,
+ &:disabled:active::-moz-range-thumb,
+ &:disabled::-moz-range-thumb {
+ background: $mdlext-light-range-bg-color;
+ }
+
+ &:disabled + .mdl-slider__background-flex > .mdl-slider__background-lower {
+ background-color: $mdlext-light-range-bg-color;
+ }
+
+ &.is-lowest-value:disabled:focus::-webkit-slider-thumb,
+ &.is-lowest-value:disabled:active::-webkit-slider-thumb,
+ &.is-lowest-value:disabled::-webkit-slider-thumb {
+ border-color: $mdlext-light-range-bg-color;
+ background: transparent;
+ }
+
+ &.is-lowest-value:disabled:focus::-moz-range-thumb,
+ &.is-lowest-value:disabled:active::-moz-range-thumb,
+ &.is-lowest-value:disabled::-moz-range-thumb {
+ border-color: $mdlext-light-range-bg-color;
+ background: transparent;
+ }
+
+ &:disabled:focus::-ms-thumb,
+ &:disabled:active::-ms-thumb,
+ &:disabled::-ms-thumb {
+ background: $mdlext-light-range-bg-color;
+ }
+
+ /* stylelint-disable */
+ &.is-lowest-value:disabled:focus::-ms-thumb,
+ &.is-lowest-value:disabled:active::-ms-thumb,
+ &.is-lowest-value:disabled::-ms-thumb {
+ background: radial-gradient(circle closest-side,
+ transparent 0%,
+ transparent 50%,
+ $mdlext-light-range-bg-color 50%,
+ $mdlext-light-range-bg-color 100%);
+ }
+
+ &:disabled::-ms-fill-lower {
+ background: linear-gradient(to right,
+ transparent,
+ transparent 25px,
+ $mdlext-light-range-bg-color 25px,
+ $mdlext-light-range-bg-color 0);
+ }
+ /* stylelint-enable */
+
+ }
+ }
+
+ .mdl-slider__background-flex {
+ background: transparent;
+ }
+
+ .mdl-slider__background-lower {
+ background: $mdlext-light-range-color;
+ }
+
+ // This one styles the upper part of the slider track.
+ .mdl-slider__background-upper {
+ background: $mdlext-light-range-bg-color;
+ }
+}
+
+
+// mdl/src/textfield/_textfield.scss
+// -----------------------------------
+.mdlext-light-color-theme {
+
+ .mdl-textfield__input {
+ border-bottom-color: $mdlext-light-input-text-bottom-border-color;
+ }
+ .mdl-textfield.is-invalid .mdl-textfield__input {
+ border-color: $mdlext-light-input-text-error-color;
+ }
+ fieldset[disabled] .mdl-textfield .mdl-textfield__input,
+ .mdl-textfield.is-disabled .mdl-textfield__input {
+ background-color: transparent;
+ border-bottom-color: $mdlext-light-input-text-disabled-color;
+ color: $mdlext-light-input-text-disabled-text-color;
+ }
+ .mdl-textfield__label {
+ color: $mdlext-light-input-text-label-color;
+ }
+ .mdl-textfield__label::after {
+ background-color: $mdlext-light-input-text-highlight-color;
+ }
+ fieldset[disabled] .mdl-textfield .mdl-textfield__label,
+ .mdl-textfield.is-disabled.is-disabled .mdl-textfield__label {
+ color: $mdlext-light-input-text-disabled-text-color;
+ }
+ .mdl-textfield--floating-label.is-focused .mdl-textfield__label,
+ .mdl-textfield--floating-label.is-dirty .mdl-textfield__label,
+ .mdl-textfield--floating-label.has-placeholder .mdl-textfield__label {
+ color: $mdlext-light-input-text-highlight-color;
+ }
+ .mdl-textfield--floating-label.is-invalid .mdl-textfield__label {
+ color: $mdlext-light-input-text-error-color;
+ }
+ .mdl-textfield.is-invalid .mdl-textfield__label::after {
+ background-color: $mdlext-light-input-text-error-color;
+ }
+ .mdl-textfield__error {
+ color: $mdlext-light-input-text-error-color;
+ }
+}
+
+
+// mdl/src/checkbox/_checkbox.scss
+// -----------------------------------
+.mdlext-light-color-theme {
+
+ .mdl-checkbox__box-outline {
+ border-color: $mdlext-light-checkbox-off-color;
+ }
+ .mdl-checkbox.is-checked .mdl-checkbox__box-outline {
+ border-color: $mdlext-light-checkbox-color;
+ }
+ fieldset[disabled] .mdl-checkbox .mdl-checkbox__box-outline,
+ .mdl-checkbox.is-disabled .mdl-checkbox__box-outline {
+ border-color: $mdlext-light-checkbox-disabled-color;
+ }
+
+ .mdl-checkbox__focus-helper {
+ background-color: transparent;
+ }
+ .mdl-checkbox.is-focused.is-checked .mdl-checkbox__focus-helper {
+ box-shadow: 0 0 0 ($checkbox-button-size / 2) $mdlext-light-checkbox-focus-color;
+ background-color: $mdlext-light-checkbox-focus-color;
+ }
+
+ .mdl-checkbox__tick-outline {
+ background: transparent;
+ }
+ .mdl-checkbox.is-checked .mdl-checkbox__tick-outline {
+ background-color: $mdlext-light-checkbox-color;
+ }
+ fieldset[disabled] .mdl-checkbox.is-checked .mdl-checkbox__tick-outline,
+ .mdl-checkbox.is-checked.is-disabled .mdl-checkbox__tick-outline {
+ background-color: $mdlext-light-checkbox-disabled-color;
+ }
+
+ fieldset[disabled] .mdl-checkbox .mdl-checkbox__label,
+ .mdl-checkbox.is-disabled .mdl-checkbox__label {
+ color: $mdlext-light-checkbox-disabled-color;
+ }
+
+ .mdl-checkbox__ripple-container .mdl-ripple {
+ background: $mdlext-light-checkbox-color;
+ }
+ fieldset[disabled] .mdl-checkbox .mdl-checkbox__ripple-container .mdl-ripple,
+ .mdl-checkbox.is-disabled .mdl-checkbox__ripple-container .mdl-ripple {
+ background: transparent;
+ }
+
+}
+
+// mdl/src/radio/_radio.scss
+// -----------------------------------
+.mdlext-light-color-theme {
+ .mdl-radio__outer-circle {
+ border-color: $mdlext-light-radio-off-color;
+ }
+ .mdl-radio.is-checked .mdl-radio__outer-circle {
+ border-color: $mdlext-light-radio-color;
+ }
+ .mdl-radio__outer-circle fieldset[disabled] .mdl-radio,
+ .mdl-radio.is-disabled .mdl-radio__outer-circle {
+ border-color: $mdlext-light-radio-disabled-color;
+ }
+
+ .mdl-radio__inner-circle {
+ background: $mdlext-light-radio-color;
+ }
+ fieldset[disabled] .mdl-radio .mdl-radio__inner-circle,
+ .mdl-radio.is-disabled .mdl-radio__inner-circle {
+ background: $mdlext-light-radio-disabled-color;
+ }
+
+ fieldset[disabled] .mdl-radio .mdl-radio__label,
+ .mdl-radio.is-disabled .mdl-radio__label {
+ color: $mdlext-light-radio-disabled-color;
+ }
+
+ .mdl-radio__ripple-container .mdl-ripple {
+ background: $mdlext-light-radio-color;
+ }
+ fieldset[disabled] .mdl-radio .mdl-radio__ripple-container .mdl-ripple,
+ .mdl-radio.is-disabled .mdl-radio__ripple-container .mdl-ripple {
+ background: transparent;
+ }
+}
+
+// mdl/src/icon-togglr/_icon-toggle.scss
+// ---------------------------------------
+.mdlext-light-color-theme {
+ .mdl-icon-toggle__label {
+ color: $mdlext-light-icon-toggle-color;
+ }
+ .mdl-icon-toggle.is-checked .mdl-icon-toggle__label {
+ color: $mdlext-light-icon-toggle-checked-color;
+ }
+ .mdl-icon-toggle.is-disabled .mdl-icon-toggle__label {
+ color: $mdlext-light-icon-toggle-disabled-color;
+ }
+ .mdl-icon-toggle.is-focused .mdl-icon-toggle__label {
+ background-color: $mdlext-light-icon-toggle-focus-color;
+ }
+ .mdl-icon-toggle.is-focused.is-checked .mdl-icon-toggle__label {
+ background-color: $mdlext-light-icon-toggle-checked-focus-color;
+ }
+ .mdl-icon-toggle__ripple-container .mdl-ripple {
+ background: $mdlext-light-icon-toggle-color;
+ }
+ .mdl-icon-toggle.is-disabled .mdl-icon-toggle__ripple-container .mdl-ripple {
+ background: transparent;
+ }
+}
+
+
+// mdl/src/switch/_switch.scss
+// -----------------------------------
+.mdlext-light-color-theme {
+
+ .mdl-switch__track {
+ background: $mdlext-light-switch-off-track-color;
+ }
+ .mdl-switch.is-checked .mdl-switch__track {
+ background: $mdlext-light-switch-track-color;
+ }
+ .mdl-switch__track fieldset[disabled] .mdl-switch,
+ .mdl-switch.is-disabled .mdl-switch__track {
+ background: $mdlext-light-switch-disabled-track-color;
+ }
+
+ .mdl-switch__thumb {
+ background: $mdlext-light-switch-off-thumb-color;
+ }
+ .mdl-switch.is-checked .mdl-switch__thumb {
+ background: $mdlext-light-switch-thumb-color;
+ }
+ .mdl-switch__thumb fieldset[disabled] .mdl-switch,
+ .mdl-switch.is-disabled .mdl-switch__thumb {
+ background: $mdlext-light-switch-disabled-thumb-color;
+ }
+
+ .mdl-switch__focus-helper {
+ background-color: transparent;
+ }
+ .mdl-switch.is-focused .mdl-switch__focus-helper {
+ background-color: rgba(0, 0, 0, 0.1);
+ }
+ .mdl-switch.is-focused.is-checked .mdl-switch__focus-helper {
+ box-shadow: 0 0 0 (($switch-ripple-size - $switch-helper-size) / 2) $mdlext-light-switch-faded-color;
+ background-color: $mdlext-light-switch-faded-color;
+ }
+
+ .mdl-switch__label fieldset[disabled] .mdl-switch,
+ .mdl-switch.is-disabled .mdl-switch__label {
+ color: $mdlext-light-switch-disabled-thumb-color;
+ }
+
+ .mdl-switch__ripple-container .mdl-ripple {
+ background: $mdlext-light-switch-color;
+ }
+ fieldset[disabled] .mdl-switch .mdl-switch__ripple-container .mdl-ripple,
+ .mdl-switch.is-disabled .mdl-switch__ripple-container .mdl-ripple {
+ background: transparent;
+ }
+}
+
+
+// mdl/src/data-table/_data-table.scss
+// -----------------------------------
+.mdlext-light-color-theme {
+
+ .mdl-data-table {
+ border-color: $mdlext-light-data-table-divider-color;
+ background-color: $mdlext-light-data-table-background-color;
+
+ tbody {
+ tr {
+ &.is-selected {
+ background-color: $mdlext-light-data-table-selection-color;
+ }
+ &:hover {
+ background-color: $mdlext-light-data-table-hover-color;
+ }
+ }
+ }
+ th {
+ color: $data-table-header-color;
+
+ &.mdl-data-table__header--sorted-ascending,
+ &.mdl-data-table__header--sorted-descending {
+ color: $mdlext-light-data-table-header-sorted-color;
+
+ &:hover {
+ &::before {
+ color: $mdlext-light-data-table-header-sorted-icon-hover-color;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+// mdl/src/menu/_menu.scss
+// -----------------------------------
+.mdlext-light-color-theme {
+
+ .mdl-menu__outline {
+ background: $mdlext-light-default-dropdown-bg-color;
+ }
+
+ .mdl-menu__item {
+ color: $mdlext-light-default-item-text-color;
+ background-color: transparent;
+ outline-color: $mdlext-light-default-item-outline-color;
+
+ &--full-bleed-divider {
+ border-bottom-color: $mdlext-light-default-item-divider-color;
+ }
+
+ &[disabled],
+ &[data-mdl-disabled] {
+ color: $mdlext-light-disabled-item-text-color;
+ background-color: transparent;
+
+ &:hover {
+ background-color: transparent;
+ }
+
+ &:focus {
+ background-color: transparent;
+ }
+
+ & .mdl-ripple {
+ background: transparent;
+ }
+ }
+
+ &:hover {
+ background-color: $mdlext-light-default-item-hover-bg-color;
+ }
+
+ &:focus {
+ background-color: $mdlext-light-default-item-focus-bg-color;
+ }
+
+ &:active {
+ background-color: $mdlext-light-default-item-active-bg-color;
+ }
+ }
+}
+
+
+// mdl/src/card/_card.scss
+// ----------------------------------------
+.mdlext-light-color-theme {
+
+ .mdl-card {
+ background: $mdlext-light-card-background-color;
+ }
+
+ .mdl-card__media {
+ background-color: $mdlext-light-card-image-placeholder-color;
+ }
+
+ .mdl-card__title {
+ color: $mdlext-light-card-text-color;
+
+ &.mdl-card--border {
+ border-bottom-color: $mdlext-light-card-border-color;
+ }
+ }
+
+ .mdl-card__title-text {
+ color: inherit;
+ }
+
+ .mdl-card__subtitle-text {
+ color: $mdlext-light-card-subtitle-color;
+ }
+
+ .mdl-card__supporting-text {
+ color: $mdlext-light-card-supporting-text-text-color;
+ }
+
+ .mdl-card__actions {
+ background-color: rgba(0, 0, 0, 0);
+
+ &.mdl-card--border {
+ border-top-color: $mdlext-light-card-border-color;
+ }
+ }
+}
+
+
+// mdlext/src/selectfield/_selectfield.scss
+// ----------------------------------------
+.mdlext-light-color-theme {
+
+ .mdlext-selectfield.is-disabled::after {
+ color: $mdlext-light-input-text-disabled-color;
+ @include mdlext-arrow(bottom, $mdlext-selectfield-arrow-width, $mdlext-selectfield-arrow-length, $mdlext-light-input-text-disabled-color);
+ }
+
+ .mdlext-selectfield__select {
+ border-bottom-color: $mdlext-light-input-text-bottom-border-color;
+ color: inherit;
+
+ option {
+ background-color: $mdlext-light-content-background-color;
+ color: $mdlext-light-text-color-primary;
+ }
+ }
+ .mdlext-selectfield.is-invalid .mdlext-selectfield__select {
+ border-color: $mdlext-light-input-text-error-color;
+ }
+ fieldset[disabled] .mdlext-selectfield .mdlext-selectfield__select,
+ .mdlext-selectfield.is-disabled .mdlext-selectfield__select {
+ background-color: transparent;
+ border-bottom-color: $mdlext-light-input-text-disabled-color;
+ color: $mdlext-light-input-text-disabled-text-color;
+ }
+
+ .mdlext-selectfield__label {
+ color: $mdlext-light-input-text-label-color;
+ }
+ fieldset[disabled] .mdlext-selectfield .mdlext-selectfield__label,
+ .mdlext-selectfield.is-disabled.is-disabled .mdlext-selectfield__label {
+ color: $mdlext-light-input-text-disabled-text-color;
+ }
+ .mdlext-selectfield--floating-label.is-focused .mdlext-selectfield__label,
+ .mdlext-selectfield--floating-label.is-dirty .mdlext-selectfield__label,
+ .mdlext-selectfield--floating-label.is-dirty.is-dirty .mdlext-selectfield__label,
+ .mdlext-selectfield--floating-label.has-placeholder .mdlext-selectfield__label {
+ color: $mdlext-light-input-text-highlight-color;
+ }
+ .mdlext-selectfield--floating-label.is-invalid .mdlext-selectfield__label {
+ color: $mdlext-light-input-text-error-color;
+ }
+ .mdlext-selectfield__label::after {
+ background-color: $mdlext-light-input-text-highlight-color;
+ }
+ .mdlext-selectfield.is-invalid .mdlext-selectfield__label::after {
+ background-color: $mdlext-light-input-text-error-color;
+ }
+
+ .mdlext-selectfield__error {
+ color: $mdlext-light-input-text-error-color;
+ }
+}
+
+// mdlext/src/menu-button/_menu-button.scss
+// ----------------------------------------
+.mdlext-menu.mdlext-light-color-theme {
+ background: $mdlext-light-default-dropdown-bg-color;
+}
+
+.mdlext-light-color-theme {
+
+ .mdlext-menu {
+ background: $mdlext-light-default-dropdown-bg-color;
+
+ &__item {
+ color: $mdlext-light-default-item-text-color;
+ background-color: $mdlext-light-default-dropdown-bg-color;
+
+ &:active,
+ &[aria-selected='true'] {
+ background-color: $mdlext-light-default-item-active-bg-color;
+ }
+ &:hover:not([disabled]) {
+ background-color: $mdlext-light-default-item-hover-bg-color;
+ }
+ &:focus {
+ outline-color: $mdlext-light-default-item-outline-color;
+ background-color: $mdlext-light-default-item-focus-bg-color;
+ }
+ &[disabled] {
+ color: $mdlext-light-disabled-item-text-color;
+
+ > * {
+ color: $mdlext-light-disabled-item-text-color;
+ }
+ }
+ }
+ &__item-separator {
+ border-bottom: 1px solid $mdlext-light-default-item-divider-color;
+ }
+ }
+}
+
+
+// mdlext/src/bordered-fields/_bordered-fields.scss
+// -------------------------------------------------
+.mdlext-light-color-theme {
+
+ .mdlext-bordered-fields {
+
+ .mdl-textfield,
+ .mdlext-selectfield {
+
+ .mdl-textfield__input,
+ .mdlext-selectfield__select {
+ background-color: $mdlext-light-bordered-field-background-color;
+ border-color: $mdlext-light-bordered-field-border-color;
+ color: $mdlext-light-bordered-field-input-text-color;
+
+ &:disabled {
+ color: $mdlext-light-bordered-field-input-text-disabled-text-color;
+ background-color: $mdlext-light-bordered-field-disabled-background-color;
+ border-color: $mdlext-light-bordered-field-disabled-border-color;
+ }
+ &:focus {
+ background-color: $mdlext-light-bordered-field-focus-background-color;
+ border-color: $mdlext-light-bordered-field-focus-border-color;
+ }
+ }
+ &.is-invalid {
+ .mdl-textfield__input,
+ .mdlext-selectfield__select {
+ color: $mdlext-light-bordered-field-input-text-error-color;
+ border-color: $mdlext-light-bordered-field-error-border-color;
+ background-color: $mdlext-light-bordered-field-error-background-color;
+
+ &:focus {
+ border-color: $mdlext-light-bordered-field-error-focus-border-color;
+ background-color: $mdlext-light-bordered-field-error-focus-background-color;
+ }
+ }
+ }
+ }
+
+ fieldset[disabled] .mdlext-selectfield::after,
+ .mdlext-selectfield.is-disabled::after {
+ color: $mdlext-light-bordered-field-input-text-disabled-text-color;
+ @include mdlext-arrow(bottom, $mdlext-selectfield-arrow-width, $mdlext-selectfield-arrow-length, $mdlext-light-bordered-field-input-text-disabled-text-color);
+ }
+
+ fieldset[disabled] .mdl-textfield .mdl-textfield__input,
+ fieldset[disabled] .mdlext-selectfield .mdlext-selectfield__select {
+ color: $mdlext-light-bordered-field-input-text-disabled-text-color;
+ background-color: $mdlext-light-bordered-field-disabled-background-color;
+ border-color: $mdlext-light-bordered-field-disabled-border-color;
+ }
+
+ .mdl-textfield,
+ .mdlext-selectfield {
+
+ .mdl-textfield__label,
+ .mdlext-selectfield__label {
+ color: $mdlext-light-bordered-field-input-text-label-color;
+ }
+ &.mdl-textfield--floating-label.is-focused.is-focused,
+ &.mdl-textfield--floating-label.is-dirty.is-dirty,
+ &.mdl-textfield--floating-label.has-placeholder,
+ &.mdlext-selectfield--floating-label.is-focused.is-focused,
+ &.mdlext-selectfield--floating-label.is-dirty.is-dirty,
+ &.mdlext-selectfield--floating-label.has-placeholder {
+
+ .mdl-textfield__label,
+ .mdlext-selectfield__label {
+ color: $mdlext-light-bordered-field-input-text-label-focus-color;
+ }
+ }
+ &.mdl-textfield--floating-label.is-disabled.is-disabled,
+ &.mdlext-selectfield--floating-label.is-disabled.is-disabled {
+
+ .mdl-textfield__label,
+ .mdlext-selectfield__label {
+ color: $mdlext-light-bordered-field-input-text-label-disabled-color;
+ }
+ }
+ &.mdl-textfield--floating-label.is-invalid.is-invalid,
+ &.mdlext-selectfield--floating-label.is-invalid.is-invalid {
+
+ .mdl-textfield__label,
+ .mdlext-selectfield__label {
+ color: $mdlext-light-bordered-field-input-text-label-error-color;
+ }
+ }
+ }
+
+ fieldset[disabled] .mdl-textfield .mdl-textfield__label,
+ fieldset[disabled] .mdl-selectfield .mdl-selectfield__label {
+ color: $mdlext-light-bordered-field-input-text-label-disabled-color;
+ }
+
+ // Icon(s) and/or button(s) inside textfield
+ .mdl-textfield,
+ .mdlext-selectfield {
+ &.is-disabled i,
+ &.is-disabled .mdl-button {
+ color: $mdlext-light-bordered-field-disabled-border-color;
+ }
+ }
+ fieldset[disabled] .mdl-textfield,
+ fieldset[disabled] .mdlext-selectfield {
+ i,
+ .mdl-button {
+ color: $mdlext-light-bordered-field-disabled-border-color;
+ }
+ }
+ }
+}
+
+
+// mdlext/src/accordion/_accordion.scss
+// ----------------------------------------
+.mdlext-light-color-theme {
+
+ .mdlext-accordion {
+
+ &__tab {
+ color: $mdlext-light-accordion-header-secondary-color;
+ background-color: $mdlext-light-accordion-header-background-color;
+
+ &:focus {
+ outline-color: $mdlext-light-accordion-header-focus-outline-color;
+ }
+ &[aria-expanded='true'] {
+ background-color: $mdlext-light-accordion-header-background-open-color;
+ }
+ &[aria-selected='true'] {
+ background-color: $mdlext-light-accordion-header-background-active-color;
+ }
+ &[disabled] {
+ background-color: $mdlext-light-accordion-header-disabled-color;
+ color: $mdlext-light-accordion-header-secondary-color-disabled;
+ pointer-events: none;
+
+ > * {
+ color: $mdlext-light-accordion-header-secondary-color-disabled;
+ }
+ }
+ &:hover:not([disabled]) {
+ background-color: $mdlext-light-accordion-header-background-hover-color;
+ }
+ &--ripple {
+ &[aria-selected='true']::before {
+ background: $mdlext-light-accordion-ripple-color;
+ }
+ }
+ }
+
+ &__tabpanel {
+ color: $mdlext-light-accordion-content-color;
+ background-color: $mdlext-light-accordion-content-background-color;
+ }
+ }
+
+ // Vertical layout
+ .mdlext-accordion {
+
+ &--vertical {
+
+ .mdlext-accordion__tab {
+ border-top: 1px solid $mdlext-light-accordion-header-border-color;
+
+ &[aria-selected='true']::after {
+ background-color: $mdlext-light-accordion-header-highlight-color;
+ }
+ }
+ .mdlext-accordion__tabpanel {
+ border-top: 1px solid $mdlext-light-accordion-header-border-color;
+ }
+ }
+ }
+
+ // Horizontal layout
+ .mdlext-accordion {
+
+ &--horizontal {
+
+ .mdlext-accordion__tab {
+ border-left: 1px solid $mdlext-light-accordion-header-border-color;
+
+ &[aria-selected='true']::after {
+ background-color: $mdlext-light-accordion-header-highlight-color;
+ }
+ }
+ .mdlext-accordion__tabpanel {
+ border-left: 1px solid $mdlext-light-accordion-header-border-color;
+ }
+ }
+ }
+
+ .mdlext-accordion {
+
+ &__panel:first-child > &__tab {
+ // Use container to set outer borders
+ border-top-color: transparent;
+ border-left-color: transparent;
+ }
+ }
+
+ // Making accordion appear disabled.
+ // Note: does not prevent tabbing into a disabled accordion
+ .mdlext-accordion[disabled] {
+ .mdlext-accordion__tab {
+ background-color: $mdlext-light-accordion-header-disabled-color;
+ color: $mdlext-light-accordion-header-secondary-color-disabled;
+
+ > * {
+ color: $mdlext-light-accordion-header-secondary-color-disabled;
+ }
+ }
+ .mdlext-accordion__tabpanel {
+ opacity: 0.8;
+ filter: blur(1px) grayscale(80%);
+ }
+ }
+}
diff --git a/node_modules/mdl-ext/src/color-themes/readme.md b/node_modules/mdl-ext/src/color-themes/readme.md
new file mode 100644
index 0000000..6266567
--- /dev/null
+++ b/node_modules/mdl-ext/src/color-themes/readme.md
@@ -0,0 +1,104 @@
+# Color Themes
+![Color Themes](../../etc/palette.png)
+
+The **color-themes** component demonstrates how you can create your own themes of
+[material design colors](https://www.google.com/design/spec/style/color.html).
+
+## Introduction
+Material Design Lite provides only one color theme, but in many web designs more than one theme is required, e.g. a
+dark theme and a light theme. This component provides the necessary SASS files to use two additional color themes in MDL.
+
+### To include a MDLEXT color theme component:
+ 1. Code a block element, as the "outer" container, intended to hold all of the color theme.
+```html
+<section>
+</section>
+```
+
+ 2. Add one of the `mdlext-light-color-theme` or `mdlext-dark-color-theme` classes to the block element using the `class` attribute.
+```html
+<section class="mdlext-light-color-theme">
+</section>
+```
+
+ 3. Add the MDL components that shuld be rendered with the spesified color theme.
+```html
+<section class="mdlext-light-color-theme">
+ <div class="mdl-card mdl-shadow--2dp">
+ <header class="mdl-card__title mdl-color--primary mdl-color-text--primary-contrast">
+ <button class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
+ <i class="material-icons">view_headline</i>
+ </button>
+ <h2 class="mdl-card__title-text">A card with a Color Theme</h2>
+ <div class="mdl-layout-spacer"></div>
+ <button class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
+ <i class="material-icons">share</i>
+ </button>
+ </header>
+ <div class="mdl-card__supporting-text">
+ Some supporting text ...
+ </div>
+ <footer class="mdl-card__actions mdl-card--border">
+ <a class="mdl-button mdl-button--colored mdl-js-button mdl-js-ripple-effect">
+ Read more
+ </a>
+ <div class="mdl-layout-spacer"></div>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">share</i></button>
+ </footer>
+ </div>
+ <p>More content ...</p>
+</section>
+```
+
+### Create your own color theme
+Creating your own color theme is simple. For each of the themes, light or dark, you must modify six SASS variables.
+The variables defines the primary and accent colors for the theme, and their corresponding contrast colors.
+
+Start by picking some sensible primary and accent colors from the
+[material color plaette](https://www.google.com/design/spec/style/color.html#color-color-palette) - or use one of the
+web based platte generators as an aid. The [material palette](http://www.materialpalette.com/) is used for this example.
+
+Pick a primary and an accent color from the [material palette](http://www.materialpalette.com/), e.g. grey/yellow.
+Download the SASS version of the palette and translate the variables to the MDLEXT color theme.
+
+The downloaded material palette SASS variables:
+```sass
+$primary-color-dark: #616161
+$primary-color: #9E9E9E
+$primary-color-light: #F5F5F5
+$primary-color-text: #212121
+$accent-color: #FFEB3B
+$primary-text-color: #212121
+$secondary-text-color: #727272
+$divider-color: #B6B6B6
+```
+
+Open the MDLEXT [color-themes](./_color-themes.scss) SASS file and translate material palette variables to MDLEXT color theme:
+```sass
+$mdlext-light-color-primary: #9E9E9E;
+$mdlext-light-color-primary-dark: #616161;
+$mdlext-light-color-primary-light: #9E9E9E; // Fallback color. Set to color-primary if fallback is not needed
+$mdlext-light-color-primary-contrast: #F5F5F5;
+$mdlext-light-color-accent: #FFEB3B;
+$mdlext-light-color-accent-light: #FFEB3B; // Fallback color. Set to color-primary if fallback is not needed
+$mdlext-light-color-accent-contrast: #FFFFFF;
+```
+
+Save the modified variables to your own SASS project, recompile and try out your new theme.
+
+There are a few more SASS variables you can modify - and they should be relativeley self explanatory. By default these
+values are set in accordance with the guidance given in the
+[material design colors](https://www.google.com/design/spec/style/color.html) guide.
+
+#### Examples
+See the [example code](./snippets/color-themes.html).
+
+## Configuration options
+
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements to MDL components.
+The table below lists the available classes and their effects.
+
+| MDLEXT class | Effect | Remarks |
+|-----------|--------|---------|
+| `mdlext-light-color-theme` | Defines container as an MDLEXT light color theme component | Required on an "outer" block element|
+| `mdlext-dark-color-theme` | Defines container as an MDLEXT dark coolor theme component | Required on an "outer" block element|
diff --git a/node_modules/mdl-ext/src/color-themes/snippets/color-themes.html b/node_modules/mdl-ext/src/color-themes/snippets/color-themes.html
new file mode 100644
index 0000000..1dc8ae5
--- /dev/null
+++ b/node_modules/mdl-ext/src/color-themes/snippets/color-themes.html
@@ -0,0 +1,2769 @@
+<style>
+ .demo-theme-container {
+ margin: 0 auto 32px;
+ /*max-width: 800px;*/
+ }
+
+ .demo-theme-container table.info,
+ .demo-card-grid table.info {
+ width: 100%
+ }
+ .demo-theme-container table.info th,
+ .demo-card-grid table.info th {
+ padding-right: 40px;
+ vertical-align: middle;
+ text-align: left;
+ width: 30%;
+ }
+ .demo-theme-container section,
+ .demo-card-grid section {
+ margin: 0 16px;
+ }
+
+ .demo-badge-grid {
+ }
+ .demo-badge-grid .mdl-cell {
+ text-align: center;
+ }
+ .demo-badge-grid .mdl-cell p {
+ margin-top: 32px;
+ }
+
+ .demo-button-grid {
+ }
+ .demo-button-grid .mdl-cell {
+ text-align: center;
+ padding: 12px 4px;
+ }
+
+ .demo-toggle-grid {
+ }
+ .demo-toggle-grid .mdl-cell p {
+ margin-top: 16px;
+ }
+
+ .demo-slider-grid {
+ }
+ .demo-slider-grid p {
+ margin-top: 16px;
+ }
+
+ .textfield-demo-container {
+ }
+
+ .textfield-demo-container .mdl-cell {
+ padding: 0 4px 8px 0;
+ }
+
+ .textfield-demo-container .mdl-cell p {
+ margin-bottom: 0;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+
+
+ .demo-menu {
+ padding-top: 16px;
+ max-width: 300px;
+ }
+ .demo-menu-container {
+ position: relative;
+ width: 100%;
+ }
+ .demo-menu-bar {
+ box-sizing: border-box;
+ height: 64px;
+ width: 100%;
+ padding: 16px;
+ }
+ .demo-menu-background-light {
+ background: white;
+ height: 148px;
+ width: 100%;
+ }
+ .demo-menu-background-dark {
+ background: #212121;
+ height: 148px;
+ width: 100%;
+ }
+
+
+ .mdl-card {
+ width: auto;
+ }
+ .mdl-card__media {
+ margin: 0;
+ text-align: center;
+ }
+ .mdl-card__media > img {
+ max-width: 100%;
+ height: auto;
+ }
+ .mdl-card__supporting-text {
+ width: auto;
+ }
+ .mdl-card__actions {
+ display: flex;
+ }
+
+
+ .borderedfield-demo-container .mdl-cell {
+ padding: 0 4px 8px 0;
+ }
+
+ .borderedfield-demo-container .mdl-cell p {
+ margin-bottom: 0;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+
+ /* File input example */
+ .mdl-button--file input {
+ cursor: pointer;
+ opacity: 0;
+ width: 1px;
+ height: 1px;
+ }
+
+</style>
+
+
+<datalist id="languages">
+ <option value="HTML">
+ <option value="CSS">
+ <option value="JavaScript">
+ <option value="Java">
+ <option value="Ruby">
+ <option value="PHP">
+ <option value="Go">
+ <option value="Erlang">
+ <option value="Python">
+ <option value="C">
+ <option value="C#">
+ <option value="C++">
+</datalist>
+
+
+<div class="mdl-grid demo-card-grid" style="margin-bottom: 32px;">
+
+ <div class="mdl-cell mdl-cell--6-col mdl-cell--4-col-tablet mdl-cell--4-col-phone mdlext-light-color-theme">
+ <div class="mdl-card mdl-shadow--2dp">
+ <header class="mdl-card__title mdl-color--primary mdl-color-text--primary-contrast">
+ <button class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
+ <i class="material-icons">view_headline</i>
+ </button>
+ <h2 class="mdl-card__title-text">Light Theme</h2>
+ <div class="mdl-layout-spacer"></div>
+ <button class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
+ <i class="material-icons">share</i>
+ </button>
+ </header>
+ <figure class="mdl-card__media">
+ <img src="./images/_DSC7535-2.jpg" alt="">
+ </figure>
+ <section style="margin-top:16px">
+ <table class="info">
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary-dark</th>
+ <td class="mdl-color--primary-dark mdl-color-text--primary-contrast">primary dark</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary</th>
+ <td class="mdl-color--primary mdl-color-text--primary-contrast">primary</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">accent</th>
+ <td class="mdl-color--accent mdl-color-text--accent-contrast">accent</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary-dark</th>
+ <td class="mdl-color--primary-contrast mdl-color-text--primary-dark">primary dark, inverted</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary</th>
+ <td class="mdl-color--primary-contrast mdl-color-text--primary">primary, inverted</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">accent</th>
+ <td class="mdl-color--accent-contrast mdl-color-text--accent">accent, inverted</td>
+ </tr>
+ </table>
+ </section>
+
+ <div class="mdl-card__supporting-text">
+ Card Supporting Text
+ </div>
+
+ <footer class="mdl-card__actions mdl-card--border">
+ <a class="mdl-button mdl-button--colored mdl-js-button mdl-js-ripple-effect">
+ Read more
+ </a>
+ <div class="mdl-layout-spacer"></div>
+ <button class="mdl-button mdl-button--icon"><i class="material-icons">radio</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">favorite</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">share</i></button>
+ </footer>
+ </div>
+
+ </div>
+
+
+ <div class="mdl-cell mdl-cell--6-col mdl-cell--4-col-tablet mdl-cell--4-col-phone mdlext-dark-color-theme">
+
+ <div class="mdl-card mdl-shadow--2dp">
+ <header class="mdl-card__title mdl-color--primary mdl-color-text--primary-contrast">
+ <button class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
+ <i class="material-icons">view_headline</i>
+ </button>
+ <h2 class="mdl-card__title-text">Dark Theme</h2>
+ <div class="mdl-layout-spacer"></div>
+ <button class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect">
+ <i class="material-icons">share</i>
+ </button>
+ </header>
+ <figure class="mdl-card__media">
+ <img src="./images/_DSC7535-2.jpg" alt="">
+ </figure>
+ <section style="margin-top:16px">
+ <table class="info">
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary-dark</th>
+ <td class="mdl-color--primary-dark mdl-color-text--primary-contrast">primary dark</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary</th>
+ <td class="mdl-color--primary mdl-color-text--primary-contrast">primary</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">accent</th>
+ <td class="mdl-color--accent mdl-color-text--accent-contrast">accent</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary-dark</th>
+ <td class="mdl-color--primary-contrast mdl-color-text--primary-dark">primary dark, inverted</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary</th>
+ <td class="mdl-color--primary-contrast mdl-color-text--primary">primary, inverted</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">accent</th>
+ <td class="mdl-color--accent-contrast mdl-color-text--accent">accent, inverted</td>
+ </tr>
+ </table>
+ </section>
+
+ <div class="mdl-card__supporting-text">
+ Card Supporting Text
+ </div>
+
+ <footer class="mdl-card__actions mdl-card--border">
+ <a class="mdl-button mdl-button--colored mdl-js-button mdl-js-ripple-effect">
+ Read more
+ </a>
+ <div class="mdl-layout-spacer"></div>
+ <button class="mdl-button mdl-button--icon"><i class="material-icons">radio</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">favorite</i></button>
+ <button class="mdl-button mdl-button--icon mdl-button--colored"><i class="material-icons">share</i></button>
+ </footer>
+ </div>
+
+ </div>
+
+</div>
+
+
+
+
+<h2>Light Color Theme</h2>
+
+<div class="demo-theme-container mdlext-light-color-theme">
+
+ <section>
+ <table class="info">
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">.mdl-typography--</th>
+ <td class="mdl-typography--title">Scale & Basic Styles</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">display-4</th>
+ <td class="mdl-typography--display-4">Light 112px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">display-3</th>
+ <td class="mdl-typography--display-3">Regular 56px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">display-2</th>
+ <td class="mdl-typography--display-2">Regular 45px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">display-1</th>
+ <td class="mdl-typography--display-1">Regular 34px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">headline</th>
+ <td class="mdl-typography--headline">Regular 24px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">title</th>
+ <td class="mdl-typography--title">Medium 20px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">subhead</th>
+ <td class="mdl-typography--subhead">Regular 16px (Device), Regular 15px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">body-2</th>
+ <td class="mdl-typography--body-2">Medium 14px (Device), Medium 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">body-1</th>
+ <td class="mdl-typography--body-1">Regular 14px (Device), Regular 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">body-2-force-preferred-font</th>
+ <td class="mdl-typography--body-2-force-preferred-font">Medium 14px (Device), Medium 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">body-1-force-preferred-font</th>
+ <td class="mdl-typography--body-1-force-preferred-font">Regular 14px (Device), Regular 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">caption</th>
+ <td class="mdl-typography--caption">Regular 12px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">menu</th>
+ <td class="mdl-typography--menu">Medium 14px (Device), Medium 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">button</th>
+ <td class="mdl-typography--button">Medium (All Caps) 14px</td>
+ </tr>
+
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary-dark</th>
+ <td class="mdl-color--primary-dark mdl-color-text--primary-contrast">mdl-color--primary-dark mdl-color-text--primary-contrast</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary</th>
+ <td class="mdl-color--primary mdl-color-text--primary-contrast">mdl-color--primary mdl-color-text--primary-contrast</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">accent</th>
+ <td class="mdl-color--accent mdl-color-text--accent-contrast">mdl-color--accent mdl-color-text--accent-contrast</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary-dark</th>
+ <td class="mdl-color--primary-contrast mdl-color-text--primary-dark">mdl-color--primary-contrast mdl-color-text--primary-dark</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary</th>
+ <td class="mdl-color--primary-contrast mdl-color-text--primary">mdl-color-text--primary</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">accent</th>
+ <td class="mdl-color--accent-contrast mdl-color-text--accent">mdl-color--accent-contrast mdl-color-text--accent</td>
+ </tr>
+ </table>
+ </section>
+
+ <section>
+ <h1>Base font</h1>
+
+ <p>Material Design Lite start’s with a base font of</p>
+ <ul>
+ <li>A size of 14px</li>
+ <li>A weight of 400</li>
+ <li>A line height of 20px</li>
+ </ul>
+
+ <p class="mdl-typography--body-1">Regular 14px (Device), Regular 13px (Desktop)</p>
+ <p class="mdl-typography--body-1-force-preferred-font">Regular 14px (Device), Regular 13px (Desktop)</p>
+ <p class="mdl-typography--body-2">Medium 14px (Device), Medium 13px (Desktop)</p>
+ <p class="mdl-typography--body-2-color-contrast">Body with color contrast</p>
+ <p class="mdl-typography--body-2-force-preferred-font">Medium 14px (Device), Medium 13px (Desktop)</p>
+ <p><a href="#" onclick="return false">An anchor</a></p>
+
+ <h1>Headings</h1>
+ <h1>h1 (56px) <small>Subtitle</small></h1>
+ <h2>h2 (45px) <small>Subtitle</small></h2>
+ <h3>h3 (34px) <small>Subtitle</small></h3>
+ <h4>h4 (24px) <small>Subtitle</small></h4>
+ <h5>h5 (20px) <small>Subtitle</small></h5>
+ <h6>h6 (16px) <small>Subtitle</small></h6>
+ </section>
+
+
+ <!-- textfields -->
+ <section class = "textfield-demo-container">
+
+ <div class="mdl-grid mdl-grid--no-spacing">
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield">
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" list="languages" placeholder="Select a programming language" required>
+ <label class="mdl-textfield__label">Programming Language</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?" disabled value="123">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--expandable mdl-textfield--floating-label">
+ <label class="mdl-button mdl-js-button mdl-button--icon" for="mdl-expandable-demo3">
+ <i class="material-icons">search</i>
+ </label>
+ <div class="mdl-textfield__expandable-holder">
+ <input class="mdl-textfield__input" type="text" name="q" value="" id="mdl-expandable-demo3" pattern=".{3,}" />
+ <label class="mdl-textfield__label" for="mdl-expandable-demo1">Expandable Input</label>
+ </div>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--8-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--full-width mdl-textfield--floating-label">
+ <textarea class="mdl-textfield__input" rows= "3"></textarea>
+ <label class="mdl-textfield__label">Text lines...</label>
+ </div>
+ </div>
+
+ </div>
+
+ </section>
+
+
+ <!-- Selectfield -->
+ <section style="margin-bottom: 16px;">
+ <div class="mdl-grid mdl-grid--no-spacing">
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select" disabled>
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+ </div>
+ </section>
+
+
+ <!-- bordered fields -->
+ <section class="mdlext-bordered-fields" style="margin-top:16px;">
+
+ <div class="mdl-grid mdl-grid--no-spacing">
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" list="languages" placeholder="Select a language" required>
+ <label class="mdl-textfield__label">Programming language</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Numeric with floating label</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?" disabled value="123">
+ <label class="mdl-textfield__label" >Disabled floating label</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right ">
+ <input class="mdl-textfield__input" type="text" id="uploadfile12" readonly>
+ <label class="mdl-textfield__label">File (work in progress)</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--primary mdl-button--icon mdl-button--file" for="uploadfile12">
+ <i class="material-icons">attach_file</i>
+ <input type="file" id="uploadBtn12">
+ </label>
+ </div>
+ <!--
+ // Need a script to work properly - something like this
+ -->
+ <script>
+ (function() {
+ 'use strict';
+ document.querySelector('#uploadBtn12').addEventListener('change', function() {
+ var n = document.querySelector("#uploadfile12");
+ n.value = this.files[0].name;
+ n.parentNode.classList.add('is-dirty');
+ });
+ }());
+ </script>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text" disabled>
+ <label class="mdl-textfield__label">Text, disabled</label>
+ <i class="material-icons">fingerprint</i>
+ </div>
+ </div>
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right">
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select" disabled>
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label mdlext-bordered-fields__icon-left">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label mdlext-bordered-fields__icon-left">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+ <select class="mdlext-selectfield__select" disabled>
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right">
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <i class="material-icons">fingerprint</i>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <i class="material-icons">fingerprint</i>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+
+ <input class="mdl-textfield__input" type="text" disabled>
+ <label class="mdl-textfield__label">Text...</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+ </div>
+
+ <fieldset disabled>
+ <legend>Disabled fieldset</legend>
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ <option value="option6">option 5 abcdefghijklmnopqrstuvw0123456789</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </fieldset>
+
+ </section>
+
+
+ <!-- Badges -->
+ <section style="margin-top:16px">
+ <div class="mdl-grid demo-badge-grid">
+ <div class="mdl-cell mdl-cell--2-col">
+ <span class="mdl-badge" data-badge="4">Inbox</span>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <span class="material-icons mdl-badge" data-badge="1">account_box</span>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <span class="mdl-badge" data-badge="♥">Mood</span>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <span class="material-icons mdl-badge" data-badge="♥">account_box</span>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <a href="#" onclick="return false" class="mdl-badge" data-badge="5">Inbox</a>
+ </div>
+ </div>
+ </section>
+
+ <!-- Buttons -->
+ <section>
+ <div class="mdl-grid demo-button-grid">
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab">
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab" disabled>
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored">
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab">
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab" disabled>
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised">
+ Raised
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised" disabled>
+ Disabled
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
+ Colored
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">
+ Accent
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored mdl-js-ripple-effect">
+ <i class="material-icons">settings</i> Settings
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect animated bounce">
+ <i class="material-icons">favorite</i> Fav
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button">
+ Flat
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button" disabled>
+ Disabled
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--primary">
+ Colored
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--accent">
+ Accent
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button">
+ <i class="material-icons">snooze</i> Ring, ring...
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">mood</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--icon mdl-button--colored">
+ <i class="material-icons">mood</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-color--lime mdl-button--accent">
+ <i class="material-icons">cloud</i>
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-color--deep-orange-100 mdl-js-ripple-effect">
+ <i class="material-icons">settings</i> Settings
+ </button>
+ </div>
+ </div>
+ </section>
+
+
+ <!-- Toggles -->
+ <section>
+ <div class="mdl-grid demo-toggle-grid">
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-checkbox__input" checked>
+ <span class="mdl-checkbox__label">Checkbox</span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-checkbox__input">
+ <span class="mdl-checkbox__label">Checkbox</span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-checkbox__input" checked disabled>
+ <span class="mdl-checkbox__label">Checkbox</span>
+ </label>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-radio mdl-js-radio mdl-js-ripple-effect">
+ <input type="radio" class="mdl-radio__button" name="options30" value="1" checked>
+ <span class="mdl-radio__label">First</span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-radio mdl-js-radio mdl-js-ripple-effect">
+ <input type="radio" class="mdl-radio__button" name="options30" value="2">
+ <span class="mdl-radio__label">Second</span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-radio mdl-js-radio mdl-js-ripple-effect">
+ <input type="radio" class="mdl-radio__button" name="options30" value="3" disabled>
+ <span class="mdl-radio__label">Third</span>
+ </label>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-icon-toggle mdl-js-icon-toggle mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-icon-toggle__input" checked>
+ <i class="mdl-icon-toggle__label material-icons">format_bold</i>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-icon-toggle mdl-js-icon-toggle mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-icon-toggle__input">
+ <i class="mdl-icon-toggle__label material-icons">format_italic</i>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-icon-toggle mdl-js-icon-toggle mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-icon-toggle__input" disabled>
+ <i class="mdl-icon-toggle__label material-icons">format_italic</i>
+ </label>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-switch__input" checked>
+ <span class="mdl-switch__label"></span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-switch__input">
+ <span class="mdl-switch__label"></span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-switch__input" disabled>
+ <span class="mdl-switch__label"></span>
+ </label>
+ </div>
+ </div>
+ </section>
+
+
+ <!-- Sliders -->
+ <section>
+ <div class="mdl-grid demo-slider-grid">
+ <div class="mdl-cell mdl-cell--4-col mdl-cell--2-col-phone">
+ <!-- Default Slider -->
+ <input class="mdl-slider mdl-js-slider" type="range" min="0" max="100" value="0">
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col mdl-cell--2-col-phone">
+ <!-- Slider with Starting Value -->
+ <input class="mdl-slider mdl-js-slider" type="range" min="0" max="100" value="25">
+ </div>
+ </div>
+ </section>
+
+
+ <!-- Data table -->
+ <section>
+ <table class="mdl-data-table mdl-js-data-table mdl-data-table--selectable mdl-shadow--2dp">
+ <thead>
+ <tr>
+ <th class="mdl-data-table__cell--non-numeric">Materials</th>
+ <th>Quantity</th>
+ <th>Unit price</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="mdl-data-table__cell--non-numeric">Acrylic (Transparent)</td>
+ <td>25</td>
+ <td>$2.90</td>
+ </tr>
+ <tr>
+ <td class="mdl-data-table__cell--non-numeric">Plywood (Birch)</td>
+ <td>50</td>
+ <td>$1.25</td>
+ </tr>
+ <tr>
+ <td class="mdl-data-table__cell--non-numeric">Laminate (Gold on Blue)</td>
+ <td>10</td>
+ <td>$2.35</td>
+ </tr>
+ </tbody>
+ </table>
+ </section>
+
+
+ <!-- Menu -->
+ <!--
+ <section>
+ <div class="demo-menu demo-menu__lower-left">
+ <div class="demo-menu-container mdl-shadow--2dp mdl-color--primary-dark mdl-color-text--primary-contrast">
+ <div class="demo-menu-bar">
+ <button id="demo-menu-lower-left-30" class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">more_vert</i>
+ </button>
+ <ul class="mdl-menu mdl-menu--bottom-left mdl-js-menu mdl-js-ripple-effect" for="demo-menu-lower-left-30">
+ <li class="mdl-menu__item">Some Action</li>
+ <li class="mdl-menu__item">Another Action</li>
+ <li disabled class="mdl-menu__item">Disabled Action</li>
+ <li class="mdl-menu__item">Yet Another Action</li>
+ </ul>
+
+ <span>Menu lower left</span>
+
+ </div>
+ <div class="demo-menu-background-light"></div>
+ </div>
+ </div>
+ </section>
+ -->
+
+ <!-- Menu button -->
+ <section style="padding-bottom:16px">
+ <h4>Menu button</h4>
+
+ <button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+ <i class="material-icons">gesture</i>
+ <span class="mdlext-menu-button__caption">Select</span>
+ <i class="material-icons mdlext-aria-expanded-more-less"></i>
+ </button>
+ <ul class="mdlext-menu mdlext-light-color-theme" hidden >
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">info</i>
+ <span class="mdlext-menu__item__caption">Menu item #1</span>
+ </li>
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">help_outline</i>
+ <span class="mdlext-menu__item__caption">Menu item #2. A long text to check ellipsis overflow 0123456789</span>
+ <i class="material-icons md-18">radio</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item" disabled>
+ <span class="mdlext-menu__item__caption">Menu item #3, disabled</span>
+ <i class="material-icons md-18">accessibility</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #IV</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #V</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VI</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VII</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ Menu item #n
+ </li>
+ </ul>
+ </section>
+
+</div>
+
+
+
+<!-- Dark theme -->
+<h2>Dark Color Theme</h2>
+
+
+<div class="demo-theme-container mdlext-dark-color-theme">
+
+ <section>
+ <table class="info">
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">.mdl-typography--</th>
+ <td class="mdl-typography--title">Scale & Basic Styles</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">display-4</th>
+ <td class="mdl-typography--display-4">Light 112px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">display-3</th>
+ <td class="mdl-typography--display-3">Regular 56px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">display-2</th>
+ <td class="mdl-typography--display-2">Regular 45px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">display-1</th>
+ <td class="mdl-typography--display-1">Regular 34px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">headline</th>
+ <td class="mdl-typography--headline">Regular 24px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">title</th>
+ <td class="mdl-typography--title">Medium 20px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">subhead</th>
+ <td class="mdl-typography--subhead">Regular 16px (Device), Regular 15px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">body-2</th>
+ <td class="mdl-typography--body-2">Medium 14px (Device), Medium 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">body-1</th>
+ <td class="mdl-typography--body-1">Regular 14px (Device), Regular 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">body-2-force-preferred-font</th>
+ <td class="mdl-typography--body-2-force-preferred-font">Medium 14px (Device), Medium 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">body-1-force-preferred-font</th>
+ <td class="mdl-typography--body-1-force-preferred-font">Regular 14px (Device), Regular 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">caption</th>
+ <td class="mdl-typography--caption">Regular 12px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">menu</th>
+ <td class="mdl-typography--menu">Medium 14px (Device), Medium 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">button</th>
+ <td class="mdl-typography--button">Medium (All Caps) 14px</td>
+ </tr>
+
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary-dark</th>
+ <td class="mdl-color--primary-dark mdl-color-text--primary-contrast">mdl-color--primary-dark mdl-color-text--primary-contrast</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary</th>
+ <td class="mdl-color--primary mdl-color-text--primary-contrast">mdl-color--primary mdl-color-text--primary-contrast</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">accent</th>
+ <td class="mdl-color--accent mdl-color-text--accent-contrast">mdl-color--accent mdl-color-text--accent-contrast</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary-dark</th>
+ <td class="mdl-color--primary-contrast mdl-color-text--primary-dark">mdl-color--primary-contrast mdl-color-text--primary-dark</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary</th>
+ <td class="mdl-color--primary-contrast mdl-color-text--primary">mdl-color-text--primary</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">accent</th>
+ <td class="mdl-color--accent-contrast mdl-color-text--accent">mdl-color--accent-contrast mdl-color-text--accent</td>
+ </tr>
+ </table>
+ </section>
+
+ <section>
+ <h1>Base font</h1>
+
+ <p>Material Design Lite start’s with a base font of</p>
+ <ul>
+ <li>A size of 14px</li>
+ <li>A weight of 400</li>
+ <li>A line height of 20px</li>
+ </ul>
+
+ <p class="mdl-typography--body-1">Regular 14px (Device), Regular 13px (Desktop)</p>
+ <p class="mdl-typography--body-1-force-preferred-font">Regular 14px (Device), Regular 13px (Desktop)</p>
+ <p class="mdl-typography--body-2">Medium 14px (Device), Medium 13px (Desktop)</p>
+ <p class="mdl-typography--body-2-color-contrast">Body with color contrast</p>
+ <p class="mdl-typography--body-2-force-preferred-font">Medium 14px (Device), Medium 13px (Desktop)</p>
+ <p><a href="#" onclick="return false">An anchor</a></p>
+
+ <h1>Headings</h1>
+ <h1>h1 (56px) <small>Subtitle</small></h1>
+ <h2>h2 (45px) <small>Subtitle</small></h2>
+ <h3>h3 (34px) <small>Subtitle</small></h3>
+ <h4>h4 (24px) <small>Subtitle</small></h4>
+ <h5>h5 (20px) <small>Subtitle</small></h5>
+ <h6>h6 (16px) <small>Subtitle</small></h6>
+ </section>
+
+
+ <!-- textfields -->
+ <section class = "textfield-demo-container">
+
+ <div class="mdl-grid mdl-grid--no-spacing">
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield">
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" list="languages" placeholder="Select a programming language" required>
+ <label class="mdl-textfield__label">Programming Language</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?" disabled value="123">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--expandable mdl-textfield--floating-label">
+ <label class="mdl-button mdl-js-button mdl-button--icon" for="mdl-expandable-demo2">
+ <i class="material-icons">search</i>
+ </label>
+ <div class="mdl-textfield__expandable-holder">
+ <input class="mdl-textfield__input" type="text" name="q" value="" id="mdl-expandable-demo2" pattern=".{3,}" />
+ <label class="mdl-textfield__label" for="mdl-expandable-demo2">Expandable Input</label>
+ </div>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--8-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--full-width mdl-textfield--floating-label">
+ <textarea class="mdl-textfield__input" rows= "3" ></textarea>
+ <label class="mdl-textfield__label">Text lines...</label>
+ </div>
+ </div>
+
+ </div>
+
+ </section>
+
+
+
+ <!-- Selectfield -->
+ <section style="margin-bottom: 16px;">
+ <div class="mdl-grid mdl-grid--no-spacing">
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield">
+ <select class="mdlext-selectfield__select" name="mdl-professsion3">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select" name="mdl-professsion20">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select" name="mdl-professsion22" disabled>
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+ </div>
+ </section>
+
+
+
+ <!-- bordered fields -->
+ <section class="mdlext-bordered-fields" style="margin-top:16px;">
+
+ <div class="mdl-grid mdl-grid--no-spacing">
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" list="languages" placeholder="Select a language" required>
+ <label class="mdl-textfield__label">Programming language</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Numeric with floating label</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?" disabled value="123">
+ <label class="mdl-textfield__label" >Disabled floating label</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right ">
+ <input class="mdl-textfield__input" type="text" id="uploadfile22" readonly>
+ <label class="mdl-textfield__label">File (work in progress)</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--primary mdl-button--icon mdl-button--file" for="uploadfile22">
+ <i class="material-icons">attach_file</i>
+ <input type="file" id="uploadBtn22">
+ </label>
+ </div>
+ <!--
+ // Need a script to work properly - something like this
+ -->
+ <script>
+ (function() {
+ 'use strict';
+ document.querySelector('#uploadBtn22').addEventListener('change', function() {
+ var n = document.querySelector("#uploadfile22");
+ n.value = this.files[0].name;
+ n.parentNode.classList.add('is-dirty');
+ });
+ }());
+ </script>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text" disabled>
+ <label class="mdl-textfield__label">Text, disabled</label>
+ <i class="material-icons">fingerprint</i>
+ </div>
+ </div>
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right">
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select" disabled>
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label mdlext-bordered-fields__icon-left">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label mdlext-bordered-fields__icon-left">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+ <select class="mdlext-selectfield__select" disabled>
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right">
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <i class="material-icons">fingerprint</i>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <i class="material-icons">fingerprint</i>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+
+ <input class="mdl-textfield__input" type="text" disabled>
+ <label class="mdl-textfield__label">Text...</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+ </div>
+
+ <fieldset disabled>
+ <legend>Disabled fieldset</legend>
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ <option value="option6">option 5 abcdefghijklmnopqrstuvw0123456789</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </fieldset>
+
+ </section>
+
+
+ <!-- Badges -->
+ <section style="margin-top:16px">
+ <div class="mdl-grid demo-badge-grid">
+ <div class="mdl-cell mdl-cell--2-col">
+ <span class="mdl-badge" data-badge="4">Inbox</span>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <span class="material-icons mdl-badge" data-badge="1">account_box</span>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <span class="mdl-badge" data-badge="♥">Mood</span>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <span class="material-icons mdl-badge" data-badge="♥">account_box</span>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <a href="#" onclick="return false" class="mdl-badge" data-badge="5">Inbox</a>
+ </div>
+ </div>
+
+ </section>
+
+
+ <!-- Buttons -->
+ <section>
+ <div class="mdl-grid demo-button-grid">
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab">
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab" disabled>
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored">
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab">
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab" disabled>
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised">
+ Raised
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised" disabled>
+ Disabled
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
+ Colored
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">
+ Accent
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored mdl-js-ripple-effect">
+ <i class="material-icons">settings</i> Settings
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect animated bounce">
+ <i class="material-icons">favorite</i> Fav
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button">
+ Flat
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button" disabled>
+ Disabled
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--primary">
+ Colored
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--accent">
+ Accent
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button">
+ <i class="material-icons">snooze</i> Ring, ring...
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">mood</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--icon mdl-button--colored">
+ <i class="material-icons">mood</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-color--lime mdl-button--accent">
+ <i class="material-icons">cloud</i>
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-color--deep-orange-100 mdl-js-ripple-effect">
+ <i class="material-icons">settings</i> Settings
+ </button>
+ </div>
+ </div>
+ </section>
+
+ <!-- Toggles -->
+ <section>
+ <div class="mdl-grid demo-toggle-grid">
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-checkbox__input" checked>
+ <span class="mdl-checkbox__label">Checkbox</span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-checkbox__input">
+ <span class="mdl-checkbox__label">Checkbox</span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-checkbox__input" checked disabled>
+ <span class="mdl-checkbox__label">Checkbox</span>
+ </label>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-radio mdl-js-radio mdl-js-ripple-effect">
+ <input type="radio" class="mdl-radio__button" name="options2" value="1" checked>
+ <span class="mdl-radio__label">First</span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-radio mdl-js-radio mdl-js-ripple-effect">
+ <input type="radio" class="mdl-radio__button" name="options2" value="2">
+ <span class="mdl-radio__label">Second</span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-radio mdl-js-radio mdl-js-ripple-effect">
+ <input type="radio" class="mdl-radio__button" name="options2" value="3" disabled>
+ <span class="mdl-radio__label">Third</span>
+ </label>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-icon-toggle mdl-js-icon-toggle mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-icon-toggle__input" checked>
+ <i class="mdl-icon-toggle__label material-icons">format_bold</i>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-icon-toggle mdl-js-icon-toggle mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-icon-toggle__input">
+ <i class="mdl-icon-toggle__label material-icons">format_italic</i>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-icon-toggle mdl-js-icon-toggle mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-icon-toggle__input" disabled>
+ <i class="mdl-icon-toggle__label material-icons">format_italic</i>
+ </label>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-switch__input" checked>
+ <span class="mdl-switch__label"></span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-switch__input">
+ <span class="mdl-switch__label"></span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-switch__input" disabled>
+ <span class="mdl-switch__label"></span>
+ </label>
+ </div>
+ </div>
+ </section>
+
+
+
+ <!-- Sliders -->
+ <section>
+ <div class="mdl-grid demo-slider-grid">
+ <div class="mdl-cell mdl-cell--4-col mdl-cell--2-col-phone">
+ <!-- Default Slider -->
+ <input class="mdl-slider mdl-js-slider" type="range" min="0" max="100" value="0">
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col mdl-cell--2-col-phone">
+ <!-- Slider with Starting Value -->
+ <input class="mdl-slider mdl-js-slider" type="range" min="0" max="100" value="25">
+ </div>
+ </div>
+ </section>
+
+
+ <!-- Data table -->
+ <section>
+ <table class="mdl-data-table mdl-js-data-table mdl-data-table--selectable mdl-shadow--2dp">
+ <thead>
+ <tr>
+ <th class="mdl-data-table__cell--non-numeric">Materials</th>
+ <th>Quantity</th>
+ <th>Unit price</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="mdl-data-table__cell--non-numeric">Acrylic (Transparent)</td>
+ <td>25</td>
+ <td>$2.90</td>
+ </tr>
+ <tr>
+ <td class="mdl-data-table__cell--non-numeric">Plywood (Birch)</td>
+ <td>50</td>
+ <td>$1.25</td>
+ </tr>
+ <tr>
+ <td class="mdl-data-table__cell--non-numeric">Laminate (Gold on Blue)</td>
+ <td>10</td>
+ <td>$2.35</td>
+ </tr>
+ </tbody>
+ </table>
+ </section>
+
+
+ <!-- Menu -->
+ <!--
+ <section>
+ <div class="demo-menu">
+ <div class="demo-menu-container mdl-shadow--2dp mdl-color--primary-dark mdl-color-text--primary-contrast">
+ <div class="demo-menu-background-dark"></div>
+ <div class="demo-menu-bar">
+ <button id="demo-menu-top-left" class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">more_vert</i>
+ </button>
+
+ <ul class="mdl-menu mdl-menu--top-left mdl-js-menu mdl-js-ripple-effect"
+ for="demo-menu-top-left">
+ <li class="mdl-menu__item">Some Action</li>
+ <li class="mdl-menu__item">Another Action</li>
+ <li disabled class="mdl-menu__item">Disabled Action</li>
+ <li class="mdl-menu__item">Yet Another Action</li>
+ </ul>
+
+ <span>Menu top left</span>
+ </div>
+ </div>
+ </div>
+ </section>
+ -->
+
+ <!-- Menu button -->
+ <section style="padding-bottom:16px">
+ <h4>Menu button</h4>
+ <button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+ <i class="material-icons">gesture</i>
+ <span class="mdlext-menu-button__caption">Select</span>
+ <i class="material-icons mdlext-aria-expanded-more-less"></i>
+ </button>
+ <ul class="mdlext-menu mdlext-dark-color-theme" hidden >
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">info</i>
+ <span class="mdlext-menu__item__caption">Menu item #1</span>
+ </li>
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">help_outline</i>
+ <span class="mdlext-menu__item__caption">Menu item #2. A long text to check ellipsis overflow 0123456789</span>
+ <i class="material-icons md-18">radio</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item" disabled>
+ <span class="mdlext-menu__item__caption">Menu item #3, disabled</span>
+ <i class="material-icons md-18">accessibility</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #IV</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #V</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VI</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VII</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ Menu item #n
+ </li>
+ </ul>
+ </section>
+
+
+</div>
+
+
+
+<h2>Default Color Theme</h2>
+
+<!-- Default theme -->
+<div class="demo-theme-container">
+
+ <section>
+ <table class="info">
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">.mdl-typography--</th>
+ <td class="mdl-typography--title">Scale & Basic Styles</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">display-4</th>
+ <td class="mdl-typography--display-4">Light 112px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">display-3</th>
+ <td class="mdl-typography--display-3">Regular 56px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">display-2</th>
+ <td class="mdl-typography--display-2">Regular 45px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">display-1</th>
+ <td class="mdl-typography--display-1">Regular 34px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">headline</th>
+ <td class="mdl-typography--headline">Regular 24px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">title</th>
+ <td class="mdl-typography--title">Medium 20px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">subhead</th>
+ <td class="mdl-typography--subhead">Regular 16px (Device), Regular 15px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">body-2</th>
+ <td class="mdl-typography--body-2">Medium 14px (Device), Medium 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">body-1</th>
+ <td class="mdl-typography--body-1">Regular 14px (Device), Regular 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">body-2-force-preferred-font</th>
+ <td class="mdl-typography--body-2-force-preferred-font">Medium 14px (Device), Medium 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">body-1-force-preferred-font</th>
+ <td class="mdl-typography--body-1-force-preferred-font">Regular 14px (Device), Regular 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">caption</th>
+ <td class="mdl-typography--caption">Regular 12px</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">menu</th>
+ <td class="mdl-typography--menu">Medium 14px (Device), Medium 13px (Desktop)</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">button</th>
+ <td class="mdl-typography--button">Medium (All Caps) 14px</td>
+ </tr>
+
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary-dark</th>
+ <td class="mdl-color--primary-dark mdl-color-text--primary-contrast">mdl-color--primary-dark mdl-color-text--primary-contrast</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary</th>
+ <td class="mdl-color--primary mdl-color-text--primary-contrast">mdl-color--primary mdl-color-text--primary-contrast</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">accent</th>
+ <td class="mdl-color--accent mdl-color-text--accent-contrast">mdl-color--accent mdl-color-text--accent-contrast</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary-dark</th>
+ <td class="mdl-color--primary-contrast mdl-color-text--primary-dark">mdl-color--primary-contrast mdl-color-text--primary-dark</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">primary</th>
+ <td class="mdl-color--primary-contrast mdl-color-text--primary">mdl-color-text--primary</td>
+ </tr>
+ <tr>
+ <th class="mdl-typography--caption-color-contrast">accent</th>
+ <td class="mdl-color--accent-contrast mdl-color-text--accent">mdl-color--accent-contrast mdl-color-text--accent</td>
+ </tr>
+ </table>
+ </section>
+
+ <section>
+ <h1>Base font</h1>
+
+ <p>Material Design Lite start’s with a base font of</p>
+ <ul>
+ <li>A size of 14px</li>
+ <li>A weight of 400</li>
+ <li>A line height of 20px</li>
+ </ul>
+
+ <p class="mdl-typography--body-1">Regular 14px (Device), Regular 13px (Desktop)</p>
+ <p class="mdl-typography--body-1-force-preferred-font">Regular 14px (Device), Regular 13px (Desktop)</p>
+ <p class="mdl-typography--body-2">Medium 14px (Device), Medium 13px (Desktop)</p>
+ <p class="mdl-typography--body-2-color-contrast">Body with color contrast</p>
+ <p class="mdl-typography--body-2-force-preferred-font">Medium 14px (Device), Medium 13px (Desktop)</p>
+ <p><a href="#" onclick="return false">An anchor</a></p>
+
+ <h1>Headings</h1>
+ <h1>h1 (56px) <small>Subtitle</small></h1>
+ <h2>h2 (45px) <small>Subtitle</small></h2>
+ <h3>h3 (34px) <small>Subtitle</small></h3>
+ <h4>h4 (24px) <small>Subtitle</small></h4>
+ <h5>h5 (20px) <small>Subtitle</small></h5>
+ <h6>h6 (16px) <small>Subtitle</small></h6>
+ </section>
+
+
+ <!-- textfields -->
+ <section class = "textfield-demo-container">
+
+ <div class="mdl-grid mdl-grid--no-spacing">
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield">
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" list="languages" placeholder="Select a programming language" required>
+ <label class="mdl-textfield__label">Programming Language</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?" disabled value="123">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--expandable mdl-textfield--floating-label">
+ <label class="mdl-button mdl-js-button mdl-button--icon" for="mdl-expandable-demo1">
+ <i class="material-icons">search</i>
+ </label>
+ <div class="mdl-textfield__expandable-holder">
+ <input class="mdl-textfield__input" type="text" name="q" value="" id="mdl-expandable-demo1" pattern=".{3,}" />
+ <label class="mdl-textfield__label" for="mdl-expandable-demo1">Expandable Input</label>
+ </div>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--8-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--full-width mdl-textfield--floating-label">
+ <textarea class="mdl-textfield__input" rows= "3"></textarea>
+ <label class="mdl-textfield__label">Text lines...</label>
+ </div>
+ </div>
+
+ </div>
+
+ </section>
+
+
+ <!-- Selectfield -->
+ <section style="margin-bottom: 16px;">
+ <div class="mdl-grid mdl-grid--no-spacing">
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select" disabled>
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+ </div>
+ </section>
+
+
+
+ <!-- bordered fields -->
+ <section class="mdlext-bordered-fields" style="margin-top:16px;">
+
+ <div class="mdl-grid mdl-grid--no-spacing">
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" list="languages" placeholder="Select a language" required>
+ <label class="mdl-textfield__label">Programming language</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?">
+ <label class="mdl-textfield__label">Numeric with floating label</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?" disabled value="123">
+ <label class="mdl-textfield__label" >Disabled floating label</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right ">
+ <input class="mdl-textfield__input" type="text" id="uploadfile33" readonly>
+ <label class="mdl-textfield__label">File (work in progress)</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--primary mdl-button--icon mdl-button--file" for="uploadfile33">
+ <i class="material-icons">attach_file</i>
+ <input type="file" id="uploadBtn33">
+ </label>
+ </div>
+ <!--
+ // Need a script to work properly - something like this
+ -->
+ <script>
+ (function() {
+ 'use strict';
+ document.querySelector('#uploadBtn33').addEventListener('change', function() {
+ var n = document.querySelector("#uploadfile33");
+ n.value = this.files[0].name;
+ n.parentNode.classList.add('is-dirty');
+ });
+ }());
+ </script>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text" disabled>
+ <label class="mdl-textfield__label">Text, disabled</label>
+ <i class="material-icons">fingerprint</i>
+ </div>
+ </div>
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right">
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select" disabled>
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label mdlext-bordered-fields__icon-left">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label mdlext-bordered-fields__icon-left">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+ <select class="mdlext-selectfield__select" disabled>
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right">
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <i class="material-icons">fingerprint</i>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <i class="material-icons">fingerprint</i>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">phone</i>
+ </label>
+
+ <input class="mdl-textfield__input" type="text" disabled>
+ <label class="mdl-textfield__label">Text...</label>
+
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-left mdlext-bordered-fields__icon-right">
+ <i class="material-icons">radio</i>
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">Text...</label>
+ <label class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">settings_voice</i>
+ </label>
+ </div>
+ </div>
+
+ </div>
+
+ </section>
+
+
+ <!-- Badges -->
+ <section style="margin-top:16px">
+ <div class="mdl-grid demo-badge-grid">
+ <div class="mdl-cell mdl-cell--2-col">
+ <span class="mdl-badge" data-badge="4">Inbox</span>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <span class="material-icons mdl-badge" data-badge="1">account_box</span>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <span class="mdl-badge" data-badge="♥">Mood</span>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <span class="material-icons mdl-badge" data-badge="♥">account_box</span>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <a href="#" onclick="return false" class="mdl-badge" data-badge="5">Inbox</a>
+ </div>
+ </div>
+ </section>
+
+ <!-- Buttons -->
+ <section>
+ <div class="mdl-grid demo-button-grid">
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab">
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab" disabled>
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab mdl-button--colored">
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab">
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-button--mini-fab" disabled>
+ <i class="material-icons">add</i>
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised">
+ Raised
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised" disabled>
+ Disabled
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
+ Colored
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">
+ Accent
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored mdl-js-ripple-effect">
+ <i class="material-icons">settings</i> Settings
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect animated bounce">
+ <i class="material-icons">favorite</i> Fav
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button">
+ Flat
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button" disabled>
+ Disabled
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--primary">
+ Colored
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--accent">
+ Accent
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button">
+ <i class="material-icons">snooze</i> Ring, ring...
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">mood</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--icon mdl-button--colored">
+ <i class="material-icons">mood</i>
+ </button>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--fab mdl-color--lime mdl-button--accent">
+ <i class="material-icons">cloud</i>
+ </button>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--middle">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-color--deep-orange-100 mdl-js-ripple-effect">
+ <i class="material-icons">settings</i> Settings
+ </button>
+ </div>
+ </div>
+ </section>
+
+
+ <!-- Toggles -->
+ <section>
+ <div class="mdl-grid demo-toggle-grid">
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-checkbox__input" checked>
+ <span class="mdl-checkbox__label">Checkbox</span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-checkbox__input">
+ <span class="mdl-checkbox__label">Checkbox</span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-checkbox__input" checked disabled>
+ <span class="mdl-checkbox__label">Checkbox</span>
+ </label>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-radio mdl-js-radio mdl-js-ripple-effect">
+ <input type="radio" class="mdl-radio__button" name="options" value="1" checked>
+ <span class="mdl-radio__label">First</span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-radio mdl-js-radio mdl-js-ripple-effect">
+ <input type="radio" class="mdl-radio__button" name="options" value="2">
+ <span class="mdl-radio__label">Second</span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-radio mdl-js-radio mdl-js-ripple-effect">
+ <input type="radio" class="mdl-radio__button" name="options" value="3" disabled>
+ <span class="mdl-radio__label">Third</span>
+ </label>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-icon-toggle mdl-js-icon-toggle mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-icon-toggle__input" checked>
+ <i class="mdl-icon-toggle__label material-icons">format_bold</i>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-icon-toggle mdl-js-icon-toggle mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-icon-toggle__input">
+ <i class="mdl-icon-toggle__label material-icons">format_italic</i>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-icon-toggle mdl-js-icon-toggle mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-icon-toggle__input" disabled>
+ <i class="mdl-icon-toggle__label material-icons">format_italic</i>
+ </label>
+ </div>
+
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-switch__input" checked>
+ <span class="mdl-switch__label"></span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-switch__input">
+ <span class="mdl-switch__label"></span>
+ </label>
+ </div>
+ <div class="mdl-cell mdl-cell--2-col">
+ <label class="mdl-switch mdl-js-switch mdl-js-ripple-effect">
+ <input type="checkbox" class="mdl-switch__input" disabled>
+ <span class="mdl-switch__label"></span>
+ </label>
+ </div>
+ </div>
+ </section>
+
+
+ <!-- Sliders -->
+ <section>
+ <div class="mdl-grid demo-slider-grid">
+ <div class="mdl-cell mdl-cell--4-col mdl-cell--2-col-phone">
+ <!-- Default Slider -->
+ <input class="mdl-slider mdl-js-slider" type="range" min="0" max="100" value="0">
+ </div>
+
+ <div class="mdl-cell mdl-cell--4-col mdl-cell--2-col-phone">
+ <!-- Slider with Starting Value -->
+ <input class="mdl-slider mdl-js-slider" type="range" min="0" max="100" value="25">
+ </div>
+ </div>
+ </section>
+
+
+ <!-- Data table -->
+ <section>
+ <table class="mdl-data-table mdl-js-data-table mdl-data-table--selectable mdl-shadow--2dp">
+ <thead>
+ <tr>
+ <th class="mdl-data-table__cell--non-numeric">Materials</th>
+ <th>Quantity</th>
+ <th>Unit price</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="mdl-data-table__cell--non-numeric">Acrylic (Transparent)</td>
+ <td>25</td>
+ <td>$2.90</td>
+ </tr>
+ <tr>
+ <td class="mdl-data-table__cell--non-numeric">Plywood (Birch)</td>
+ <td>50</td>
+ <td>$1.25</td>
+ </tr>
+ <tr>
+ <td class="mdl-data-table__cell--non-numeric">Laminate (Gold on Blue)</td>
+ <td>10</td>
+ <td>$2.35</td>
+ </tr>
+ </tbody>
+ </table>
+ </section>
+
+
+ <!-- Menu -->
+ <!--
+ <section>
+ <div class="demo-menu demo-menu__lower-left">
+ <div class="demo-menu-container mdl-shadow--2dp mdl-color--primary-dark mdl-color-text--primary-contrast">
+ <div class="demo-menu-bar">
+ <button id="demo-menu-lower-left" class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">more_vert</i>
+ </button>
+ <ul class="mdl-menu mdl-menu--bottom-left mdl-js-menu mdl-js-ripple-effect" for="demo-menu-lower-left">
+ <li class="mdl-menu__item">Some Action</li>
+ <li class="mdl-menu__item">Another Action</li>
+ <li disabled class="mdl-menu__item">Disabled Action</li>
+ <li class="mdl-menu__item">Yet Another Action</li>
+ </ul>
+
+ <span>Menu lower left</span>
+
+ </div>
+ <div class="demo-menu-background-light"></div>
+ </div>
+ </div>
+ </section>
+ -->
+
+ <!-- Menu button -->
+ <section style="padding-bottom:16px">
+ <h4>Menu button</h4>
+ <button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+ <i class="material-icons">gesture</i>
+ <span class="mdlext-menu-button__caption">Select</span>
+ <i class="material-icons mdlext-aria-expanded-more-less"></i>
+ </button>
+ <ul class="mdlext-menu" hidden >
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">info</i>
+ <span class="mdlext-menu__item__caption">Menu item #1</span>
+ </li>
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">help_outline</i>
+ <span class="mdlext-menu__item__caption">Menu item #2. A long text to check ellipsis overflow 0123456789</span>
+ <i class="material-icons md-18">radio</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item" disabled>
+ <span class="mdlext-menu__item__caption">Menu item #3, disabled</span>
+ <i class="material-icons md-18">accessibility</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #IV</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #V</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VI</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VII</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ Menu item #n
+ </li>
+ </ul>
+ </section>
+
+</div>
+
+
diff --git a/node_modules/mdl-ext/src/demo/accordion.html b/node_modules/mdl-ext/src/demo/accordion.html
new file mode 100644
index 0000000..6a65bda
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/accordion.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Accordion</title>
+</head>
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+ <include src="../../src/accordion/snippets/accordion.html"></include>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Accordion';
+ }
+ });
+ }());
+</script>
+
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/assets/android-desktop.png b/node_modules/mdl-ext/src/demo/assets/android-desktop.png
new file mode 100644
index 0000000..f4408f5
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/assets/android-desktop.png
Binary files differ
diff --git a/node_modules/mdl-ext/src/demo/assets/favicon.png b/node_modules/mdl-ext/src/demo/assets/favicon.png
new file mode 100644
index 0000000..11ec0b5
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/assets/favicon.png
Binary files differ
diff --git a/node_modules/mdl-ext/src/demo/assets/ios-desktop.png b/node_modules/mdl-ext/src/demo/assets/ios-desktop.png
new file mode 100644
index 0000000..ac65454
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/assets/ios-desktop.png
Binary files differ
diff --git a/node_modules/mdl-ext/src/demo/assets/welcome_card.jpg b/node_modules/mdl-ext/src/demo/assets/welcome_card.jpg
new file mode 100644
index 0000000..8003e3a
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/assets/welcome_card.jpg
Binary files differ
diff --git a/node_modules/mdl-ext/src/demo/bordered-fields.html b/node_modules/mdl-ext/src/demo/bordered-fields.html
new file mode 100644
index 0000000..f1b2dae
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/bordered-fields.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Bordered Fields</title>
+</head>
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+ <include src="../../src/bordered-fields/snippets/bordered-fields.html"></include>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Bordered Fields';
+ }
+ });
+ }());
+</script>
+
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/carousel.html b/node_modules/mdl-ext/src/demo/carousel.html
new file mode 100644
index 0000000..ddd66e0
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/carousel.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Carousel</title>
+</head>
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+ <include src="../../src/carousel/snippets/carousel.html"></include>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Carousel';
+ }
+ });
+ }());
+</script>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/chrome-ripple-issue.html b/node_modules/mdl-ext/src/demo/chrome-ripple-issue.html
new file mode 100644
index 0000000..363a295
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/chrome-ripple-issue.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Chrome Ripple Issue</title>
+ <!-- styles -->
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&lang=en">
+ <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
+ <link rel="stylesheet" href="https://code.getmdl.io/1.2.1/material.indigo-pink.min.css">
+</head>
+<body>
+<!-- Always shows a header, even in smaller screens. -->
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
+ <header class="mdl-layout__header">
+ <div class="mdl-layout__header-row">
+ <!-- Title -->
+ <span class="mdl-layout-title">Title</span>
+ <!-- Add spacer, to align navigation to the right -->
+ <div class="mdl-layout-spacer"></div>
+ <!-- Navigation. We hide it in small screens. -->
+ <nav class="mdl-navigation mdl-layout--large-screen-only">
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ </nav>
+ </div>
+ </header>
+ <div class="mdl-layout__drawer">
+ <span class="mdl-layout-title">Title</span>
+ <nav class="mdl-navigation">
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ </nav>
+ </div>
+ <main class="mdl-layout__content">
+ <div class="page-content" style="padding: 128px 0 0 32px"><!-- Your content goes here -->
+
+ <h2>Ripple Issue</h2>
+ <ul>
+ <li>What MDL Version: material-design-lite-1.2.1</li>
+ <li>What browser(s) is this bug affecting (including version)? Chrome Version 53.0.2785.116 (64-bit)</li>
+ <li>What OS (and version) are you using? OSX, 10.11.6</li>
+ <li>What are the steps to reproduce the bug?
+ <ol>
+ <li>Resize browser until a scrollbar appears</li>
+ <li>Scroll the menu button into view</li>
+ <li>It's important to scroll, at least some pixels, to see the effect of this issue</li>
+ <li>Click the button to open the menu</li>
+ <li>The position of the content changes position while button ripple is animatings</li>
+ <li>Click on a menu item to close the menu</li>
+ <li>The position of the content changes while menu ripple is animating</li>
+ </ol>
+ </li>
+ <li>What is the expected behavior? The position of the should stay fixed</li>
+ <li>What is the actual behavior? The position of the page content changes</li>
+ </ul>
+
+ <div style="margin: 32px 0 640px 32px;">
+ <p><strong>Click the button</strong></p>
+ <button id="demo-menu-lower-left" style="height:46px; width:46px;"
+ class="mdl-button mdl-js-button mdl-button--icon mdl-js-ripple-effect">
+ <i class="material-icons">more_vert</i>
+ </button>
+
+ <ul class="mdl-menu mdl-menu--bottom-left mdl-js-menu mdl-js-ripple-effect"
+ for="demo-menu-lower-left">
+ <li class="mdl-menu__item">Some Action</li>
+ <li class="mdl-menu__item mdl-menu__item--full-bleed-divider">Another Action</li>
+ <li disabled class="mdl-menu__item">Disabled Action</li>
+ <li class="mdl-menu__item">Yet Another Action</li>
+ </ul>
+ </div>
+
+ <p>Some text</p>
+
+ </div>
+ </main>
+</div>
+<script src="https://code.getmdl.io/1.2.1/material.min.js" type="text/javascript" charset="utf-8"></script>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/collapsible.html b/node_modules/mdl-ext/src/demo/collapsible.html
new file mode 100644
index 0000000..c685333
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/collapsible.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Menu Button</title>
+</head>
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+ <include src="../../src/collapsible/snippets/collapsible.html"></include>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Collapsible';
+ }
+ });
+ }());
+</script>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/color-themes.html b/node_modules/mdl-ext/src/demo/color-themes.html
new file mode 100644
index 0000000..390e0b3
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/color-themes.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Color Themes</title>
+</head>
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+ <include src="../../src/color-themes/snippets/color-themes.html"></include>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Color Themes';
+ }
+ });
+ }());
+</script>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/etc/buildpages.js b/node_modules/mdl-ext/src/demo/etc/buildpages.js
new file mode 100644
index 0000000..4671609
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/etc/buildpages.js
@@ -0,0 +1,15 @@
+'use strict';
+
+// TODO: Automate this. Use Gulp
+const posthtml = require('posthtml');
+const html = require('fs').readFileSync('partials/lightbox.html').toString();
+
+posthtml()
+ .use(require('posthtml-include')({ encoding: 'utf-8', root: 'partials/' }))
+ .process(html /*, options */)
+ .then(function(result) {
+ console.log(result.html);
+ })
+ .catch(function(error) {
+ console.error(error);
+ });
diff --git a/node_modules/mdl-ext/src/demo/etc/mdl-basic-component.html b/node_modules/mdl-ext/src/demo/etc/mdl-basic-component.html
new file mode 100644
index 0000000..cd4d22f
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/etc/mdl-basic-component.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>A basic MDL component</title>
+ <link rel="stylesheet" href="../node_modules/material-design-lite/material.css" />
+</head>
+<body>
+ <div id="mount">
+ <div class="mdl-basic mdl-js-basic mdl-js-ripple-effect">
+ <p>My basic MDL component</p>
+ </div>
+ </div>
+ <script type="text/javascript" src="../node_modules/material-design-lite/material.js" charset="utf-8"></script>
+ <script type="text/javascript" src="./mdl-basic-component.js" charset="utf-8"></script>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/etc/mdl-basic-component.js b/node_modules/mdl-ext/src/demo/etc/mdl-basic-component.js
new file mode 100644
index 0000000..05db9c1
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/etc/mdl-basic-component.js
@@ -0,0 +1,79 @@
+(function() {
+ 'use strict';
+
+ /**
+ * https://github.com/google/material-design-lite/issues/4205
+ * @constructor
+ * @param {Element} element The element that will be upgraded.
+ */
+ const MaterialBasic = function MaterialBasic(element) {
+ // Stores the element.
+ this.element_ = element;
+
+ console.log('***** ctor', this.element_.classList, 'data-upgraded', this.element_.getAttribute('data-upgraded'));
+
+ // Initialize instance.
+ this.init();
+ };
+ window['MaterialBasic'] = MaterialBasic;
+
+ /**
+ * Store constants in one place so they can be updated easily.
+ *
+ * @enum {string}
+ * @private
+ */
+ MaterialBasic.prototype.Constant_ = {
+ RIPPLE_COMPONENT: 'MaterialRipple'
+ };
+
+ /**
+ * Store strings for class names defined by this component that are used in
+ * JavaScript. This allows us to simply change it in one place should we
+ * decide to modify at a later date.
+ *
+ * @enum {string}
+ * @private
+ */
+ MaterialBasic.prototype.CssClasses_ = {
+ IS_UPGRADED: 'is-upgraded',
+ JS_RIPPLE_EFFECT: 'mdl-js-ripple-effect',
+ JS_RIPPLE_EFFECT_IGNORE_EVENTS: 'mdl-js-ripple-effect--ignore-events'
+ };
+
+ /**
+ * Initialize component
+ */
+ MaterialBasic.prototype.init = function() {
+ console.log('***** init', this.element_.classList, 'data-upgraded', this.element_.getAttribute('data-upgraded'));
+
+ if (this.element_) {
+ if (this.element_.classList.contains(this.CssClasses_.JS_RIPPLE_EFFECT)) {
+ this.element_.classList.add(this.CssClasses_.JS_RIPPLE_EFFECT_IGNORE_EVENTS);
+ }
+
+ // Do the init required for this component to work
+
+ // Set upgraded flag
+ this.element_.classList.add(this.CssClasses_.IS_UPGRADED);
+ }
+ };
+
+ /**
+ * Downgrade component
+ * E.g remove listeners and clean up resources
+ */
+ MaterialBasic.prototype.mdlDowngrade_ = function() {
+ 'use strict';
+ };
+
+ // The component registers itself. It can assume componentHandler is available
+ // in the global scope.
+ /* eslint no-undef: 0 */
+ /* jshint undef:false */
+ componentHandler.register({
+ constructor: MaterialBasic,
+ classAsString: 'MaterialBasic',
+ cssClass: 'mdl-js-basic'
+ });
+})();
diff --git a/node_modules/mdl-ext/src/demo/etc/mdl-iframe-loader.js b/node_modules/mdl-ext/src/demo/etc/mdl-iframe-loader.js
new file mode 100644
index 0000000..abade92
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/etc/mdl-iframe-loader.js
@@ -0,0 +1,100 @@
+'use strict';
+
+/**
+ * Inject required CSS and JS into html fragment loaded into an <iframe>
+ * @type {{}}
+ */
+var mdlIframeLoader = {};
+(function(self) {
+
+ // The CSS and JS needed to run MDL snippets in an <iframe>
+
+ // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
+ try {
+ new window.CustomEvent('test');
+ } catch(e) {
+ var CustomEvent = function(event, params) {
+ var evt;
+ params = params || {
+ bubbles: false,
+ cancelable: false,
+ detail: undefined
+ };
+
+ evt = document.createEvent('CustomEvent');
+ evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
+ return evt;
+ };
+
+ CustomEvent.prototype = window.Event.prototype;
+ window.CustomEvent = CustomEvent; // expose definition to window
+ }
+
+ var docs = [
+ { 'type': 'css', 'id': 'font-roboto-css', 'src': 'https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&lang=en' },
+ { 'type': 'css', 'id': 'material-icon-css', 'src': 'https://fonts.googleapis.com/icon?family=Material+Icons' },
+ { 'type': 'css', 'id': 'dialog-polyfill-css', 'src': 'demo/styles/dialog-polyfill.css' },
+ { 'type': 'css', 'id': 'material-css', 'src': 'https://code.getmdl.io/1.1.3/material.grey-orange.min.css' },
+ { 'type': 'css', 'id': 'mdlext-css', 'src': 'lib/mdl-ext-eqjs.css' },
+ { 'type': 'css', 'id': 'demo-css', 'src': 'demo/styles/demo.css' },
+ { 'type': 'js', 'id': 'dialog-polyfill-js', 'src': 'demo/scripts/dialog-polyfill.js' },
+ { 'type': 'js', 'id': 'material-js', 'src': 'https://code.getmdl.io/1.1.3/material.min.js' },
+ { 'type': 'js', 'id': 'eq-js', 'src': 'demo/scripts/eq.min.js' },
+ { 'type': 'js', 'id': 'mdlext-js', 'src': 'lib/index.js' }
+ ];
+
+ var joinOrigin = function(origin, src) {
+ return src.startsWith('http') ? src : origin.concat(src);
+ };
+
+ var loadResources = function( origin, loadCompleted ) {
+ var expectToLoad = docs.length;
+ var filesLoaded = 0;
+
+ for (var i = 0; i < docs.length; i++) {
+ if (document.getElementById(docs[i].id) === null) {
+ var el;
+ var src = joinOrigin(origin, docs[i].src);
+
+ if (docs[i].type === 'css') {
+ el = document.createElement('link');
+ el.href = src;
+ el.rel = 'stylesheet';
+ el.type = 'text/css';
+ }
+ else {
+ el = document.createElement('script');
+ el.src = src;
+ el.type = 'text/javascript';
+ el.async = false;
+ el.charset = 'utf-8';
+ }
+ el.id = docs[i].id;
+ el.onload = function () {
+ filesLoaded++;
+ if(filesLoaded >= expectToLoad) {
+ loadCompleted();
+ }
+ };
+ document.head.appendChild(el);
+ }
+ else {
+ expectToLoad--;
+ }
+ }
+ };
+
+ /**
+ * Inject required CSS and JS into html fragment loaded into an <iframe>
+ * @param origin path relative to root of this project, e.g. "../../../
+ */
+ self.load = function( origin ) {
+ loadResources( origin, function () {
+ if(window.componentHandler) {
+ window.componentHandler.upgradeDom();
+ }
+ });
+ };
+
+ return self;
+})(mdlIframeLoader);
diff --git a/node_modules/mdl-ext/src/demo/formatfield.html b/node_modules/mdl-ext/src/demo/formatfield.html
new file mode 100644
index 0000000..8e55b6a
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/formatfield.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Format Field</title>
+</head>
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+ <include src="../../src/formatfield/snippets/formatfield.html"></include>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Formatted Fields';
+ }
+ });
+ }());
+</script>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/grid.html b/node_modules/mdl-ext/src/demo/grid.html
new file mode 100644
index 0000000..1336b07
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/grid.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Grid</title>
+</head>
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+ <include src="../../src/grid/snippets/grid.html"></include>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Grid';
+ }
+ });
+ }());
+</script>
+
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/include/_drawer.html b/node_modules/mdl-ext/src/demo/include/_drawer.html
new file mode 100644
index 0000000..b6bafd4
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/include/_drawer.html
@@ -0,0 +1,81 @@
+<style>
+ /* Ugly CSS! Only for demo. */
+
+ #demo-drawer-accordion {
+ height: 100%;
+ }
+
+ #demo-drawer-accordion .mdlext-accordion__tab {
+ height: 64px;
+ min-height: 64px;
+ min-width: 64px;
+ padding-left: 16px;
+ }
+
+ .is-small-screen #demo-drawer-accordion .mdlext-accordion__tab {
+ height: 56px;
+ min-height: 56px;
+ min-width: 56px;
+ }
+
+ #demo-drawer-accordion .mdlext-accordion__tabpanel,
+ #demo-drawer-accordion .mdlext-accordion__tabpanel nav {
+ padding: 0;
+ }
+
+ #demo-drawer-accordion .mdlext-accordion__tabpanel .mdl-navigation__link {
+ color: rgba(255, 255, 255, 0.87);
+ }
+
+ #demo-drawer-accordion .mdlext-accordion__tabpanel .mdl-navigation__link:hover {
+ background-color: #212121;
+ }
+
+</style>
+
+
+<aside class="mdl-layout__drawer">
+
+ <ul id="demo-drawer-accordion"
+ class="mdlext-accordion mdlext-js-accordion mdlext-accordion--vertical mdlext-js-ripple-effect mdlext-js-animation-effect mdlext-dark-color-theme"
+ aria-multiselectable="false">
+
+ <li class="mdlext-accordion__panel">
+ <header class="mdlext-accordion__tab" aria-expanded="true">
+ <span class="mdlext-accordion__tab__caption">MDL Extensions</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel">
+ <nav class="mdl-navigation">
+ <a class="mdl-navigation__link" href="accordion.html">Accordion</a>
+ <a class="mdl-navigation__link" href="bordered-fields.html">Bordered Fields</a>
+ <a class="mdl-navigation__link" href="collapsible.html">Collapsible</a>
+ <a class="mdl-navigation__link" href="color-themes.html">Color Themes</a>
+ <a class="mdl-navigation__link" href="formatfield.html">Formatted Fields</a>
+ <a class="mdl-navigation__link" href="grid.html">Grid</a>
+ <a class="mdl-navigation__link" href="carousel.html">Image Carousel</a>
+ <a class="mdl-navigation__link" href="lightboard.html">Lightboard</a>
+ <a class="mdl-navigation__link" href="lightbox.html">Lightbox</a>
+ <a class="mdl-navigation__link" href="menu-button.html">Menu Button</a>
+ <a class="mdl-navigation__link" href="selectfield.html">Selectfield</a>
+ </nav>
+ </section>
+ </li>
+ <li class="mdlext-accordion__panel">
+ <header class="mdlext-accordion__tab">
+ <span class="mdlext-accordion__tab__caption">Sticky headers</span>
+ <i class="mdlext-aria-toggle-material-icons"></i>
+ </header>
+ <section class="mdlext-accordion__tabpanel">
+ <nav class="mdl-navigation">
+ <a class="mdl-navigation__link" href="sticky-header.html">Sticky Header I</a>
+ <a class="mdl-navigation__link" href="sticky-header-ii.html">Sticky Header II</a>
+ <a class="mdl-navigation__link" href="sticky-header-iii.html">Sticky Header III</a>
+ <a class="mdl-navigation__link" href="sticky-header-iv.html">Sticky Header IV</a>
+ <a class="mdl-navigation__link" href="sticky-header-v.html">Sticky Header V</a>
+ <a class="mdl-navigation__link" href="sticky-header-vi.html">Sticky Header VI</a>
+ </nav>
+ </section>
+ </li>
+ </ul>
+</aside>
diff --git a/node_modules/mdl-ext/src/demo/include/_head.html b/node_modules/mdl-ext/src/demo/include/_head.html
new file mode 100644
index 0000000..1f582ce
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/include/_head.html
@@ -0,0 +1,26 @@
+<meta charset="utf-8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="description" content="A front-end template that helps you build fast, modern mobile web apps.">
+<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
+<title>Material Design Lite Extensions</title>
+
+<!-- Fallback to homescreen for Chrome <39 on Android -->
+<meta name="mobile-web-app-capable" content="yes">
+<meta name="application-name" content="Material Design Lite Extensions">
+<link rel="icon" sizes="192x192" href="./assets/android-desktop.png">
+
+<!-- Add to homescreen for Safari on iOS -->
+<meta name="apple-mobile-web-app-capable" content="yes">
+<meta name="apple-mobile-web-app-status-bar-style" content="black">
+<meta name="apple-mobile-web-app-title" content="Material Design Lite Extensions">
+<link rel="apple-touch-icon" href="./assets/ios-desktop.png">
+
+<link rel="shortcut icon" href="./assets/favicon.png">
+
+<!-- styles -->
+<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&lang=en">
+<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
+<link rel="stylesheet" href="styles/dialog-polyfill.css">
+<link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.indigo-pink.min.css">
+<link rel="stylesheet" href="../lib/mdl-ext-eqjs.min.css">
+<link rel="stylesheet" href="./styles/demo.css">
diff --git a/node_modules/mdl-ext/src/demo/include/_header-row.html b/node_modules/mdl-ext/src/demo/include/_header-row.html
new file mode 100644
index 0000000..4bd3add
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/include/_header-row.html
@@ -0,0 +1,24 @@
+<div class="mdl-layout__header-row">
+
+ <!-- Title -->
+ <span id="header-title" class="mdl-layout-title">Title goes here</span>
+
+ <!-- Add spacer, to align navigation to the right -->
+ <div class="mdl-layout-spacer"></div>
+
+ <label id="go-home" class="mdl-button mdl-js-button mdl-button--icon mdl-button--colored">
+ <a href="index.html">
+ <i class="material-icons">home</i>
+ </a>
+ </label>
+
+ <button id="header-menu" class="mdl-button mdl-js-button mdl-button--icon">
+ <i class="material-icons">more_vert</i>
+ </button>
+ <ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect" for="header-menu">
+ <li class="mdl-menu__item">Some Action</li>
+ <li class="mdl-menu__item">Another Action</li>
+ <li disabled class="mdl-menu__item">Disabled Action</li>
+ <li class="mdl-menu__item">Yet Another Action</li>
+ </ul>
+</div>
diff --git a/node_modules/mdl-ext/src/demo/include/_header.html b/node_modules/mdl-ext/src/demo/include/_header.html
new file mode 100644
index 0000000..b11f9bf
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/include/_header.html
@@ -0,0 +1,3 @@
+<header class="mdl-layout__header mdlext-layout__sticky-header mdlext-js-sticky-header">
+ <include src="include/_header-row.html"></include>
+</header>
diff --git a/node_modules/mdl-ext/src/demo/include/_index.html b/node_modules/mdl-ext/src/demo/include/_index.html
new file mode 100644
index 0000000..1945e28
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/include/_index.html
@@ -0,0 +1,54 @@
+<h5 class="mdlext-demo-header">mdl-ext</h5>
+<p>Material Design Lite Ext (MDLEXT).
+ Components built with the
+ <a href="https://github.com/google/material-design-lite">Google Material Design Lite</a>
+ framework.
+</p>
+
+<h3>Components provided</h3>
+
+<h4>Accordion</h4>
+<p>A WAI-ARIA friendly accordion component with vertcial or horizontal layout.</p>
+
+<h4>Bordered Fields</h4>
+<p>The Material Design Lite Ext (MDLEXT) bordered fieldscomponent demonstrates
+ how you can create your own theme of MDL text fields.
+</p>
+
+<h4>Collapsible</h4>
+<p>A collapsible is a component to mark expandable and collapsible regions.</p>
+
+<h4>Color Themes</h4>
+<p>MDL provides only one color theme. Many designs require more than one theme, e.g. a dark theme and a light theme.</p>
+
+<h4>Grid</h4>
+<p>A responsive grid based on element queries in favour of media queries.</p>
+
+<h4>Image Carousel</h4>
+<p>A responsive, WAI-ARIA friendly, image carousel.</p>
+
+<h4>Lightboard</h4>
+<p>A lightboard is a translucent surface illuminated from behind, used for
+ situations where a shape laid upon the surface needs to be seen with high contrast.
+ In the "old days" of photography photograpers used a lightboard to get a quick
+ view of, sorting and organizing their slides.
+</p>
+
+<h4>Lightbox</h4>
+<p>A lightbox displays an image filling the screen, and dimming out the rest of
+ the web page. It acts as a modal dialog using the <code><dialog></code>
+ element as a container for the lightbox.
+</p>
+
+<h4>Menu Button</h4>
+<p>A WAI-ARIA friendly menu button component/widget with roles, attributes and behavior in accordance with the
+ specification given in WAI-ARIA Authoring Practices, section 2.20.
+</p>
+
+<h4>Selectfield</h4>
+<p>The Material Design Lite Ext (MDLEXT) select field component is an enhanced version
+ of the standard [HTML <code><select></code> element.
+</p>
+
+<h4>Sticky Header</h4>
+<p>A sticky header makes site navigation easily accessible anywhere on the page and saves content space at the same.</p>
diff --git a/node_modules/mdl-ext/src/demo/include/_interactive-body-filler.html b/node_modules/mdl-ext/src/demo/include/_interactive-body-filler.html
new file mode 100644
index 0000000..e8103c1
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/include/_interactive-body-filler.html
@@ -0,0 +1,52 @@
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Sticky Header';
+ }
+ });
+
+ var btn = document.querySelector('#a-button');
+ btn.addEventListener('click', function() {
+
+ var content = document.querySelector('.mdl-layout__content');
+ content.insertAdjacentHTML('beforeend',
+ '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In porttitor lorem eu faucibus aliquet. ' +
+ 'In vehicula risus turpis, ut dictum ante tristique et. Aenean ultricies sed urna ac condimentum. ' +
+ 'Vivamus nisl tortor, ultricies at aliquam nec, semper at purus. Duis purus tortor, laoreet eget ante a, ' +
+ 'rhoncus vulputate lorem. Pellentesque id enim ut massa posuere vestibulum sit amet eget elit. Nulla quis ' +
+ 'euismod massa, id varius dui. Ut congue urna non ipsum placerat rhoncus. Curabitur a sollicitudin diam. ' +
+ 'Donec id lectus eleifend, blandit magna a, mattis turpis. Fusce non tellus pulvinar, finibus dui ac, ' +
+ 'porttitor ante. Vestibulum et commodo purus, et tincidunt nulla. Suspendisse blandit sodales est, nec ' +
+ 'luctus sem sollicitudin in. Etiam libero tellus, porttitor sit amet velit a, commodo sodales neque.</p>' +
+ '<p>Maecenas id sodales lacus, eu ullamcorper nibh. Sed posuere consectetur nunc nec dapibus. Nam tristique ' +
+ 'ex vel urna dapibus luctus. Phasellus eget mi ac tortor aliquet auctor non vitae risus. Cum sociis natoque ' +
+ 'penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec et egestas elit. Sed id lorem enim.' +
+ 'Aliquam maximus enim sed tincidunt pretium.</p>' +
+ '<p>Phasellus dictum, leo vel bibendum efficitur, mauris metus volutpat magna, at pharetra libero dolor id ' +
+ 'tellus. Mauris convallis tempus libero, sit amet suscipit massa maximus a. Duis ut dignissim nulla, nec ' +
+ 'gravida purus. Proin eget erat justo. Phasellus congue sapien eleifend sapien mollis, nec molestie eros ' +
+ 'efficitur. Pellentesque et diam at risus ultrices pharetra nec in augue. Phasellus vestibulum, lacus a ' +
+ 'dictum vulputate, mauris nisi dictum massa, in venenatis felis sapien a nunc. Integer mi tellus, imperdiet ' +
+ 'vel dignissim sed, fringilla ut urna.</p>' +
+ '<p>Suspendisse potenti. Pellentesque eget suscipit orci, at tempor est. Cras sed sollicitudin nunc. Donec ' +
+ 'convallis, arcu a euismod cursus, arcu odio pharetra lectus, vitae feugiat diam massa vestibulum metus. In ' +
+ 'odio tellus, consectetur eget est et, vehicula hendrerit dolor. Ut ultrices nulla tellus, sit amet ' +
+ 'consectetur dolor aliquet quis. Etiam non fermentum dolor.</p>' +
+ '<p>Donec accumsan risus in lectus sollicitudin ' +
+ 'vulputate. Praesent condimentum a leo at interdum. Donec ' +
+ 'pharetra congue erat a accumsan. Aliquam gravida ' +
+ 'lobortis mi, id elementum sapien ultrices vel. ' +
+ 'Pellentesque habitant morbi tristique senectus et ' +
+ 'netus et malesuada fames ac turpis egestas. Proin ' +
+ 'consequat enim orci, nec blandit lorem luctus ut. ' +
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. ' +
+ 'Etiam pretium nunc non metus gravida, nec tincidunt ' +
+ 'tortor volutpat. Aliquam erat volutpat. Curabitur ' +
+ 'varius purus ac auctor pharetra.</p>');
+ });
+
+ }());
+</script>
diff --git a/node_modules/mdl-ext/src/demo/include/_scripts.html b/node_modules/mdl-ext/src/demo/include/_scripts.html
new file mode 100644
index 0000000..97011e6
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/include/_scripts.html
@@ -0,0 +1,5 @@
+<script src="scripts/dialog-polyfill.js" type="text/javascript" charset="utf-8"></script>
+<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=default,es6"></script>
+<script src="scripts/eq.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="https://code.getmdl.io/1.2.1/material.min.js" type="text/javascript" charset="utf-8"></script>
+<script src="../lib/mdl-ext.min.js" type="text/javascript" charset="utf-8"></script>
diff --git a/node_modules/mdl-ext/src/demo/index.html b/node_modules/mdl-ext/src/demo/index.html
new file mode 100644
index 0000000..3aa4e01
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/index.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions</title>
+</head>
+
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+ <include src="include/_index.html"></include>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Material Design Lite Extensions';
+ }
+ });
+ }());
+</script>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/lightboard.html b/node_modules/mdl-ext/src/demo/lightboard.html
new file mode 100644
index 0000000..93adf1c
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/lightboard.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Lightboard</title>
+</head>
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+ <include src="../../src/lightboard/snippets/lightboard.html"></include>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Lightboard';
+ }
+ });
+ }());
+</script>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/lightbox.html b/node_modules/mdl-ext/src/demo/lightbox.html
new file mode 100644
index 0000000..6b774bf
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/lightbox.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Lightbox</title>
+</head>
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+ <include src="../../src/lightbox/snippets/lightbox.html"></include>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Lightbox';
+ }
+ });
+ }());
+</script>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/menu-button.html b/node_modules/mdl-ext/src/demo/menu-button.html
new file mode 100644
index 0000000..0ea10e4
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/menu-button.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Menu Button</title>
+</head>
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+ <include src="../../src/menu-button/snippets/menu-button.html"></include>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Menu Button';
+ }
+ });
+ }());
+</script>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/resize-observer.html b/node_modules/mdl-ext/src/demo/resize-observer.html
new file mode 100644
index 0000000..905db53
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/resize-observer.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Resize Observer</title>
+</head>
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+ <include src="../../src/utils/snippets/resize-observer.html"></include>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Resize Observer';
+ }
+ });
+ }());
+</script>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/selectfield.html b/node_modules/mdl-ext/src/demo/selectfield.html
new file mode 100644
index 0000000..089b5d9
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/selectfield.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Selectfield</title>
+</head>
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+ <include src="../../src/selectfield/snippets/selectfield.html"></include>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<script>
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+ var title = document.querySelector('#header-title');
+ if(title) {
+ title.innerHTML = 'Selectfield';
+ }
+ });
+ }());
+</script>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/sticky-header-ii.html b/node_modules/mdl-ext/src/demo/sticky-header-ii.html
new file mode 100644
index 0000000..794c54e
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/sticky-header-ii.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Sticky Header</title>
+</head>
+
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
+
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+
+ <main id="mount" class="mdl-layout__content">
+
+ <h5>Sticky Header, Drawer (not fixed)</h5>
+
+ <p>A sticky header makes site navigation easily accessible anywhere on the page and saves content space at the same.</p>
+ <p>The header should auto-hide, i.e. hiding the header automatically when a user starts scrolling down the page
+ and bringing the header back when a user might need it: they reach the bottom of the page or start scrolling up.</p>
+ <p class="mdl-typography--subhead">To see how the sticky header works, click the button a few
+ times to add content. Next scroll the page up and down.</p>
+ <button id="a-button" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent">
+ Click to add more content
+ </button>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<include src="include/_interactive-body-filler.html"></include>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/sticky-header-iii.html b/node_modules/mdl-ext/src/demo/sticky-header-iii.html
new file mode 100644
index 0000000..e6da56b
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/sticky-header-iii.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Sticky Header</title>
+</head>
+
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
+
+ <include src="include/_header.html"></include>
+
+ <main id="mount" class="mdl-layout__content">
+
+ <h5>Sticky Header, No Drawer</h5>
+
+ <p>A sticky header makes site navigation easily accessible anywhere on the page and saves content space at the same.</p>
+ <p>The header should auto-hide, i.e. hiding the header automatically when a user starts scrolling down the page
+ and bringing the header back when a user might need it: they reach the bottom of the page or start scrolling up.</p>
+ <p class="mdl-typography--subhead">To see how the sticky header works, click the button a few
+ times to add content. Next scroll the page up and down.</p>
+ <button id="a-button" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent">
+ Click to add more content
+ </button>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<include src="include/_interactive-body-filler.html"></include>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/sticky-header-iv.html b/node_modules/mdl-ext/src/demo/sticky-header-iv.html
new file mode 100644
index 0000000..2b91ae3
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/sticky-header-iv.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Sticky Header</title>
+</head>
+
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+
+ <header class="mdl-layout__header mdl-layout__header--waterfall mdlext-layout__sticky-header mdlext-js-sticky-header">
+ <include src="include/_header-row.html"></include>
+
+ <div class="mdl-layout__header-row">
+ <div class="mdl-layout-spacer"></div>
+ <nav class="mdl-navigation">
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ </nav>
+ </div>
+ </header>
+
+ <include src="include/_drawer.html"></include>
+
+ <main id="mount" class="mdl-layout__content">
+
+ <h5>Sticky Header, Waterfall, Fixed Drawer</h5>
+
+ <p>A sticky header makes site navigation easily accessible anywhere on the page and saves content space at the same.</p>
+ <p>The header should auto-hide, i.e. hiding the header automatically when a user starts scrolling down the page
+ and bringing the header back when a user might need it: they reach the bottom of the page or start scrolling up.</p>
+ <p class="mdl-typography--subhead">To see how the sticky header works, click the button a few
+ times to add content. Next scroll the page up and down.</p>
+ <button id="a-button" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent">
+ Click to add more content
+ </button>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<include src="include/_interactive-body-filler.html"></include>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/sticky-header-v.html b/node_modules/mdl-ext/src/demo/sticky-header-v.html
new file mode 100644
index 0000000..99027e4
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/sticky-header-v.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Sticky Header</title>
+</head>
+
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
+
+ <header class="mdl-layout__header mdl-layout__header--waterfall mdlext-layout__sticky-header mdlext-js-sticky-header">
+ <include src="include/_header-row.html"></include>
+
+ <div class="mdl-layout__header-row">
+ <div class="mdl-layout-spacer"></div>
+ <nav class="mdl-navigation">
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ </nav>
+ </div>
+ </header>
+
+ <include src="include/_drawer.html"></include>
+
+ <main id="mount" class="mdl-layout__content">
+
+ <h5>Sticky Header, Waterfall, Drawer (not fixed)</h5>
+
+ <p>A sticky header makes site navigation easily accessible anywhere on the page and saves content space at the same.</p>
+ <p>The header should auto-hide, i.e. hiding the header automatically when a user starts scrolling down the page
+ and bringing the header back when a user might need it: they reach the bottom of the page or start scrolling up.</p>
+ <p class="mdl-typography--subhead">To see how the sticky header works, click the button a few
+ times to add content. Next scroll the page up and down.</p>
+ <button id="a-button" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent">
+ Click to add more content
+ </button>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<include src="include/_interactive-body-filler.html"></include>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/sticky-header-vi.html b/node_modules/mdl-ext/src/demo/sticky-header-vi.html
new file mode 100644
index 0000000..840b8bc
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/sticky-header-vi.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Sticky Header</title>
+</head>
+
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
+
+ <header class="mdl-layout__header mdl-layout__header--waterfall mdlext-layout__sticky-header mdlext-js-sticky-header">
+ <include src="include/_header-row.html"></include>
+
+ <div class="mdl-layout__header-row">
+ <div class="mdl-layout-spacer"></div>
+ <nav class="mdl-navigation">
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ <a class="mdl-navigation__link" href="">Link</a>
+ </nav>
+ </div>
+ </header>
+
+ <main id="mount" class="mdl-layout__content">
+
+ <h5>Sticky Header, Waterfall, No Drawer</h5>
+
+ <p>A sticky header makes site navigation easily accessible anywhere on the page and saves content space at the same.</p>
+ <p>The header should auto-hide, i.e. hiding the header automatically when a user starts scrolling down the page
+ and bringing the header back when a user might need it: they reach the bottom of the page or start scrolling up.</p>
+ <p class="mdl-typography--subhead">To see how the sticky header works, click the button a few
+ times to add content. Next scroll the page up and down.</p>
+ <button id="a-button" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent">
+ Click to add more content
+ </button>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<include src="include/_interactive-body-filler.html"></include>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/sticky-header.html b/node_modules/mdl-ext/src/demo/sticky-header.html
new file mode 100644
index 0000000..6e7080a
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/sticky-header.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <include src="include/_head.html"></include>
+ <title>Material Design Lite Extensions - Sticky Header</title>
+</head>
+
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <include src="include/_header.html"></include>
+ <include src="include/_drawer.html"></include>
+ <main id="mount" class="mdl-layout__content">
+
+ <h5>Sticky Header, Fixed Drawer Example</h5>
+
+ <p>A sticky header makes site navigation easily accessible anywhere on the page and saves content space at the same.</p>
+ <p>The header should auto-hide, i.e. hiding the header automatically when a user starts scrolling down the page
+ and bringing the header back when a user might need it: they reach the bottom of the page or start scrolling up.</p>
+ <p class="mdl-typography--subhead">To see how the sticky header works, click the button a few
+ times to add content. Next scroll the page up and down.</p>
+ <button id="a-button" class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent">
+ Click to add more content
+ </button>
+ </main>
+</div>
+<include src="include/_scripts.html"></include>
+<include src="include/_interactive-body-filler.html"></include>
+</body>
+</html>
diff --git a/node_modules/mdl-ext/src/demo/styles/demo.css b/node_modules/mdl-ext/src/demo/styles/demo.css
new file mode 100644
index 0000000..28151ef
--- /dev/null
+++ b/node_modules/mdl-ext/src/demo/styles/demo.css
@@ -0,0 +1,69 @@
+html {
+ box-sizing: border-box;
+}
+*, *::before, *::after, input[type="search"] {
+ box-sizing: inherit;
+}
+
+body {
+ overflow: hidden; /* Needed by Chrome OSX and IOS to avoid "double" scrollbars when a menu opens */
+}
+
+#mount {
+ padding-left: 12px;
+ padding-right: 8px;
+ height:100%;
+}
+
+#mount > *:first-child:not(h5) {
+ padding-top: 16px;
+}
+
+.is-small-screen #mount {
+ padding-left: 4px;
+ padding-right: 4px;
+}
+
+/* Rules for sizing the icon */
+/* Not provided in "material-design-icons/iconfont/material-icon.css" */
+
+.material-icons.md-12 {
+ font-size: 12px;
+ }
+.material-icons.md-16 {
+ font-size: 16px;
+}
+.material-icons.md-18 {
+ font-size: 18px;
+ }
+.material-icons.md-24 {
+ font-size: 24px;
+ }
+.material-icons.md-32 {
+ font-size: 24px;
+ }
+.material-icons.md-36 {
+ font-size: 36px;
+ }
+.material-icons.md-48 {
+ font-size: 48px;
+ }
+.material-icons.md-56 {
+ font-size: 56px;
+}
+
+/* Rules for using icons as black on a light background. */
+.material-icons.md-dark {
+ color: rgba(0, 0, 0, 0.54);
+}
+.material-icons.md-dark.md-inactive {
+ color: rgba(0, 0, 0, 0.26);
+ }
+
+/* Rules for using icons as white on a dark background. */
+.material-icons.md-light {
+ color: rgba(255, 255, 255, 1);
+}
+.material-icons.md-light.md-inactive {
+ color: rgba(255, 255, 255, 0.3);
+ }
diff --git a/node_modules/mdl-ext/src/dialog/dialog.scss b/node_modules/mdl-ext/src/dialog/dialog.scss
new file mode 100644
index 0000000..fb74849
--- /dev/null
+++ b/node_modules/mdl-ext/src/dialog/dialog.scss
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2015 Google Inc. All Rights Reserved.
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SASS based on css from Google Chrome Dialog polyfill, https://github.com/GoogleChrome/dialog-polyfill
+ * @include 'node_modules/dialog-polyfill/dialog-polyfill.css' before using this
+ */
+
+@import "../variables";
+
+dialog.mdlext-dialog {
+ position: absolute;
+ border: 0;
+ opacity: 0;
+ padding: $mdlext-dialog-padding;
+ background-color: $mdlext-dialog-background-color;
+
+ &[open] {
+ animation: mdlext-open-dialog $mdlext-dialog-open-animation;
+ }
+ &[open]::backdrop {
+ animation: mdlext-darken-backdrop $mdlext-dialog-backdrop-animation;
+ }
+ &[open] + .backdrop {
+ animation: mdlext-darken-backdrop $mdlext-dialog-backdrop-animation;
+ }
+}
+
+@keyframes mdlext-darken-backdrop {
+ to { background: $mdlext-dialog-backdrop-color; }
+}
+@keyframes mdlext-open-dialog {
+ to { opacity: 1; }
+}
diff --git a/node_modules/mdl-ext/src/dialog/readme.md b/node_modules/mdl-ext/src/dialog/readme.md
new file mode 100644
index 0000000..5902343
--- /dev/null
+++ b/node_modules/mdl-ext/src/dialog/readme.md
@@ -0,0 +1,30 @@
+# Dialog
+Additional styling for `<dialog>`, based on the [Google Chrome Dialog polyfill](https://github.com/GoogleChrome/dialog-polyfill).
+`@include 'node_modules/dialog-polyfill/dialog-polyfill.css'` before using this in your SASS build.
+
+## Introduction
+The Material Design Lite Ext (MDLEXT) `mdlext-dialog` class provides better control of the dialog backdrop.
+
+## Basic Usage
+Refer to the [Google Chrome Dialog polyfill](https://github.com/GoogleChrome/dialog-polyfill) documentaion amd the MDLEXT [lightbox](../lightbox) component.
+
+## Configuration options
+
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements to the dialog.
+The table below lists the available classes and their effects.
+
+| MDLEXT class | Effect | Remarks |
+|-----------|--------|---------|
+| `mdlext-dialog` | Defines container as an MDLEXT component | Required on `<dialog>` element |
+
+
+You can modify the dialog trough the following SASS variables.
+
+| SASS variable |Description | Remarks |
+|-----------|--------|---------|
+| `$mdlext-dialog-padding` | Dialog padding | default `0` |
+| `$mdlext-dialog-background-color` | Dialog background color | default `transparent` |
+| `$mdlext-dialog-backdrop-color` | Backdrop color when dialog is open | default `rgba(0,0,0,0.8)` |
+| `$mdlext-dialog-open-animation` | Animation when dialog opens | default `.5s .2s forwards` |
+| `$mdlext-dialog-backdrop-animation` | Backdrop animation when dialog opens | default `.2s forwards` |
+
diff --git a/node_modules/mdl-ext/src/formatfield/formatfield.js b/node_modules/mdl-ext/src/formatfield/formatfield.js
new file mode 100644
index 0000000..0b84819
--- /dev/null
+++ b/node_modules/mdl-ext/src/formatfield/formatfield.js
@@ -0,0 +1,280 @@
+/**
+ * @license
+ * Copyright 2016-2017 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+
+import {jsonStringToObject} from '../utils/json-utils';
+import {
+ IS_UPGRADED,
+} from '../utils/constants';
+
+const JS_FORMAT_FIELD = 'mdlext-js-formatfield';
+const FORMAT_FIELD_COMPONENT = 'MaterialExtFormatfield';
+
+/**
+ * Detect browser locale
+ * @returns {string} the locale
+ * @see http://stackoverflow.com/questions/1043339/javascript-for-detecting-browser-language-preference
+ */
+const browserLanguage = () => {
+ return navigator.languages
+ ? navigator.languages[0]
+ : navigator.language || navigator.userLanguage;
+};
+
+/**
+ * The formatfield formats an input field using language sensitive number formatting.
+ */
+
+class FormatField {
+ static timer = null;
+
+ element_;
+ input_;
+ options_ = {};
+ intlGroupSeparator_;
+ intlDecimalSeparator_;
+
+ constructor(element) {
+ this.element_ = element;
+ this.init();
+ }
+
+ clickHandler = () => {
+ clearTimeout(FormatField.timer);
+ };
+
+ focusInHandler = () => {
+ if(!(this.input.readOnly || this.input.disabled)) {
+ this.input.value = this.unformatInput();
+ //setTimeout(() => this.input.setSelectionRange(0, this.input.value.length), 20);
+ FormatField.timer = setTimeout(() => this.input.select(), 200);
+ }
+ };
+
+ focusOutHandler = () => {
+ clearTimeout(FormatField.timer);
+
+ if(!(this.input.readOnly || this.input.disabled)) {
+ this.formatValue();
+ }
+ };
+
+ get element() {
+ return this.element_;
+ }
+
+ get input() {
+ return this.input_;
+ }
+
+ get options() {
+ return this.options_;
+ }
+
+ stripSeparatorsFromValue() {
+ const doReplace = () => this.input.value
+ .replace(/\s/g, '')
+ .replace(new RegExp(this.options.groupSeparator, 'g'), '')
+ .replace(this.options.decimalSeparator, '.');
+ //.replace(this.intlGroupSeparator_, ''),
+ //.replace(this.intlDecimalSeparator_, '.');
+
+ return this.input.value ? doReplace() : this.input.value;
+ }
+
+ fixSeparators(value) {
+ const doReplace = () => value
+ .replace(new RegExp(this.intlGroupSeparator_, 'g'), this.options.groupSeparator)
+ .replace(this.intlDecimalSeparator_, this.options.decimalSeparator);
+
+ return value ? doReplace() : value;
+ }
+
+ formatValue() {
+ if(this.input.value) {
+ const v = new Intl.NumberFormat(this.options.locales, this.options)
+ .format(this.stripSeparatorsFromValue());
+
+ if('NaN' !== v) {
+ this.input.value = this.fixSeparators(v);
+ }
+ }
+ }
+
+ unformat() {
+ const doReplace = () => this.input.value
+ .replace(/\s/g, '')
+ .replace(new RegExp(this.options.groupSeparator, 'g'), '')
+ .replace(this.options.decimalSeparator, '.');
+
+ return this.input.value ? doReplace() : this.input.value;
+ }
+
+ unformatInput() {
+ const doReplace = () => this.input.value
+ .replace(/\s/g, '')
+ .replace(new RegExp(this.options.groupSeparator, 'g'), '');
+
+ return this.input.value ? doReplace() : this.input.value;
+ }
+
+ removeListeners() {
+ this.input.removeEventListener('click', this.clickHandler);
+ this.input.removeEventListener('focusin', this.focusInHandler);
+ this.input.removeEventListener('focusout', this.focusOutHandler);
+ }
+
+ init() {
+ const addListeners = () => {
+ this.input.addEventListener('click', this.clickHandler);
+ this.input.addEventListener('focusin', this.focusInHandler);
+ this.input.addEventListener('focusout', this.focusOutHandler);
+ };
+
+ const addOptions = () => {
+ const opts = this.element.getAttribute('data-formatfield-options') ||
+ this.input.getAttribute('data-formatfield-options');
+ if(opts) {
+ this.options_ = jsonStringToObject(opts, this.options);
+ }
+ };
+
+ const addLocale = () => {
+ if(!this.options.locales) {
+ this.options.locales = browserLanguage() || 'en-US'; //'nb-NO', //'en-US',
+ }
+ };
+
+ const addGrouping = () => {
+ const s = (1234.5).toLocaleString(this.options.locales, {
+ style: 'decimal',
+ useGrouping: true,
+ minimumFractionDigits: 1,
+ maximumFractionDigits: 1
+ });
+
+ this.intlGroupSeparator_ = s.charAt(1);
+ this.intlDecimalSeparator_ = s.charAt(s.length-2);
+ this.options.groupSeparator = this.options.groupSeparator || this.intlGroupSeparator_;
+ this.options.decimalSeparator = this.options.decimalSeparator || this.intlDecimalSeparator_;
+
+ if(this.options.groupSeparator === this.options.decimalSeparator) {
+ const e = `Error! options.groupSeparator, "${this.options.groupSeparator}" ` +
+ 'and options.decimalSeparator, ' +
+ `"${this.options.decimalSeparator}" should not be equal`;
+ throw new Error(e);
+ }
+ };
+
+ this.input_ = this.element.querySelector('input') || this.element;
+
+ addOptions();
+ addLocale();
+ addGrouping();
+ this.formatValue();
+ addListeners();
+ }
+
+ downgrade() {
+ this.removeListeners();
+ }
+
+}
+
+(function() {
+ 'use strict';
+
+ /**
+ * @constructor
+ * @param {HTMLElement} element The element that will be upgraded.
+ */
+ const MaterialExtFormatfield = function MaterialExtFormatfield(element) {
+ this.element_ = element;
+ this.formatField_ = null;
+
+ // Initialize instance.
+ this.init();
+ };
+ window['MaterialExtFormatfield'] = MaterialExtFormatfield;
+
+ /**
+ * Initialize component
+ */
+ MaterialExtFormatfield.prototype.init = function() {
+ if (this.element_) {
+ this.element_.classList.add(IS_UPGRADED);
+ this.formatField_ = new FormatField(this.element_);
+
+ // Listen to 'mdl-componentdowngraded' event
+ this.element_.addEventListener('mdl-componentdowngraded', this.mdlDowngrade_.bind(this));
+ }
+ };
+
+ /**
+ * Get options object
+ *
+ * @public
+ *
+ * @returns {Object} the options object
+ */
+ MaterialExtFormatfield.prototype.getOptions = function() {
+ return this.formatField_.options;
+ };
+ MaterialExtFormatfield.prototype['getOptions'] = MaterialExtFormatfield.prototype.getOptions;
+
+
+ /**
+ * A unformatted value is a string value where the locale specific decimal separator
+ * is replaced with a '.' separator and group separators are stripped.
+ * The returned value is suitable for parsing to a JavaScript numerical value.
+ *
+ * @example
+ * input.value = '1 234,5';
+ * inputElement.MaterialExtFormatfield.getUnformattedValue();
+ * // Returns '1234.5'
+ *
+ * @public
+ *
+ * @returns {String} the unformatted value
+ */
+ MaterialExtFormatfield.prototype.getUnformattedValue = function() {
+ return this.formatField_.unformat();
+ };
+ MaterialExtFormatfield.prototype['getUnformattedValue'] = MaterialExtFormatfield.prototype.getUnformattedValue;
+
+ /*
+ * Downgrade component
+ * E.g remove listeners and clean up resources
+ */
+ MaterialExtFormatfield.prototype.mdlDowngrade_ = function() {
+ this.formatField_.downgrade();
+ };
+
+ // The component registers itself. It can assume componentHandler is available
+ // in the global scope.
+ /* eslint no-undef: 0 */
+ componentHandler.register({
+ constructor: MaterialExtFormatfield,
+ classAsString: FORMAT_FIELD_COMPONENT,
+ cssClass: JS_FORMAT_FIELD,
+ widget: true
+ });
+
+})();
diff --git a/node_modules/mdl-ext/src/formatfield/readme.md b/node_modules/mdl-ext/src/formatfield/readme.md
new file mode 100644
index 0000000..c3737eb
--- /dev/null
+++ b/node_modules/mdl-ext/src/formatfield/readme.md
@@ -0,0 +1,103 @@
+#Formatfield
+![Formatfield](../../etc/formatfield.png)
+
+The formatfield component formats an input field using language sensitive
+**number formatting**. It acts as a "pluggable" component and can be added to a
+`mdl-textfield` component or to a `<input>` element.
+
+## To include a MDLEXT formatfield component:
+ 1. Code a [single-line `mdl-textfield`](https://getmdl.io/components/index.html#textfields-section)
+component.
+```html
+<div class="mdl-textfield mdl-js-textfield">
+ <input class="mdl-textfield__input" type="text"
+ pattern="-?[0-9 ]*([\.,][0-9]+)?" value="1234.5">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+</div>
+```
+
+ 2. Add the `mdlext-js-formatfield` class to define the element as a formatfield component.
+```html
+<div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield">
+ <input class="mdl-textfield__input" type="text"
+ pattern="-?[0-9 ]*([\.,][0-9]+)?" value="1234.5">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+</div>
+```
+
+ 3. Optionally add a `data-formatfield-options` attribute with the given
+[locale](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation).
+If this step is omitted, the formatfield component uses the browser language as it's locale.
+```html
+<div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield"
+ data-formatfield-options="{'locales': 'nb-NO'}">
+ <input class="mdl-textfield__input" type="text"
+ pattern="-?[0-9 ]*([\.,][0-9]+)?" value="1234.5">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+</div>
+```
+
+### Examples
+* The [snippets/formatfield.html](./snippets/formatfield.html) and the
+[tests](../../test/formatfield/formatfield.spec.js) provides more detailed examples.
+* Try out the [live demo](http://leifoolsen.github.io/mdl-ext/demo/formatfield.html)
+
+## Public methods
+
+### getOptions()
+Get component configuration options object.
+```
+var options = inputElement.MaterialExtFormatfield.getOptions();
+console.log('locales', options.locales);
+```
+
+### getUnformattedValue()
+An unformatted value is a string value where the locale specific decimal separator
+is replaced with a '.' separator and group separators are stripped.
+The returned value is suitable for parsing to a JavaScript numerical value.
+
+Example
+```javascript
+input.value = '1 234,5';
+inputElement.MaterialExtFormatfield.getUnformattedValue();
+// Returns '1234.5'
+```
+
+## Configuration options
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements
+to the formatfield.
+
+### Available classes and their effects.
+
+| MDLEXT class | Effect | Remarks |
+|--------------|--------|---------|
+|`mdlext-js-formatfield`| Assigns basic MDL behavior to formatfield. | Required. |
+
+
+### Options
+The component can be configured using the `data-formatfield-options` attribute.
+The attribute value is a JSON string with properties defined by the
+[Intl.NumberFormat object](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat).
+
+The `data-formatfield-options` attribute must be a valid JSON string.
+You can use single or double quotes for the JSON properties.
+
+Example 1, single quotes in JSON options string:
+```html
+<input class=" mdlext-js-formatfield" type="text"
+ data-formatfield-options="{'locales': 'nb-NO', 'minimumFractionDigits': 0, 'maximumFractionDigits': 0}">
+```
+
+Example 2, double quotes in JSON options string:
+```html
+<input class=" mdlext-js-formatfield" type="text"
+ data-formatfield-options='{"locales": "nb-NO", "minimumFractionDigits": 0, "maximumFractionDigits": 0}'>
+```
+
+## How to use the component programmatically
+The [tests](../../test/formatfield/formatfield.spec.js) and the
+[snippets/formatfield.html](./snippets/formatfield.html)
+provides examples on how to use the component programmatically.
diff --git a/node_modules/mdl-ext/src/formatfield/snippets/formatfield.html b/node_modules/mdl-ext/src/formatfield/snippets/formatfield.html
new file mode 100644
index 0000000..177a367
--- /dev/null
+++ b/node_modules/mdl-ext/src/formatfield/snippets/formatfield.html
@@ -0,0 +1,114 @@
+<p>The formatfield component formats an input field using
+ language sensitive number formatting. It acts as a "pluggable"
+ component. It can be added to a <code>mdl-textfield</code> component or to
+ a <code><input></code> element.
+</p>
+
+<style>
+ .mdl-data-table .mdl-textfield {
+ width: auto;
+ }
+</style>
+<table class="mdl-data-table mdl-js-data-table mdl-shadow--2dp" style="margin-top: 16px;">
+<thead>
+<tr>
+ <th class="mdl-data-table__cell--non-numeric">Language</th>
+ <th class="mdl-data-table__cell--non-numeric">Input</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+ <td class="mdl-data-table__cell--non-numeric" id="browser-lang">Browser language</td>
+ <td class="mdl-data-table__cell--non-numeric">
+ <div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield" id="sample2-component">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9, ]*([\.,][0-9]+)?"
+ id="sample2-input" value="1234.5">
+ <label class="mdl-textfield__label" for="sample2-input">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ <div id="sample2-unformatted"></div>
+ </td>
+</tr>
+<tr>
+ <td class="mdl-data-table__cell--non-numeric">nb-NO</td>
+ <td class="mdl-data-table__cell--non-numeric">
+ <div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield"
+ data-formatfield-options="{'locales': 'nb-NO'}">
+
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9 ]*([\.,][0-9]+)?" value="1234.5">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </td>
+</tr>
+<tr>
+ <td class="mdl-data-table__cell--non-numeric">en-GB</td>
+ <td class="mdl-data-table__cell--non-numeric">
+ <div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield" data-formatfield-options="{'locales': 'en-GB'}">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?" value="1234.5">
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </td>
+</tr>
+<tr>
+ <td class="mdl-data-table__cell--non-numeric">nb-NO, integer</td>
+ <td class="mdl-data-table__cell--non-numeric">
+ <div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield">
+ <input class="mdl-textfield__input" type="text" pattern="-?[0-9]*(\.[0-9]+)?"
+ data-formatfield-options="{'locales': 'nb-NO', 'minimumFractionDigits': 0,'maximumFractionDigits': 0}" value="1234.5">
+
+ <label class="mdl-textfield__label">Number...</label>
+ <span class="mdl-textfield__error">Input is not a number!</span>
+ </div>
+ </td>
+</tr>
+<tr>
+ <td class="mdl-data-table__cell--non-numeric">Percent. Input not supported</td>
+ <td class="mdl-data-table__cell--non-numeric">
+ <div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield">
+ <input class="mdl-textfield__input" type="text" readonly
+ data-formatfield-options="{'locales': 'en-GB', 'style': 'percent'}" value="0.20">
+ <label class="mdl-textfield__label">Number...</label>
+ </div>
+ </td>
+</tr>
+<tr>
+ <td class="mdl-data-table__cell--non-numeric">Currency. Input not supported</td>
+ <td class="mdl-data-table__cell--non-numeric">
+ <div class="mdl-textfield mdl-js-textfield mdlext-js-formatfield">
+ <input class="mdl-textfield__input" type="text" readonly
+ data-formatfield-options="{'locales': 'nb-NO', 'style': 'currency', 'currency': 'NOK'}" value="1234.5">
+ <label class="mdl-textfield__label">Number...</label>
+ </div>
+ </td>
+</tr>
+<tr>
+ <td class="mdl-data-table__cell--non-numeric">Input</td>
+ <td class="mdl-data-table__cell--non-numeric">
+ <input class=" mdlext-js-formatfield" type="text"
+ data-formatfield-options="{'locales': 'nb-NO'}" value="1234.5">
+ </td>
+</tr>
+</tbody>
+</table>
+
+<script>
+ (function() {
+ 'use strict';
+ window.addEventListener('load', function() {
+ var lang = navigator.languages
+ ? navigator.languages[0]
+ : navigator.language || navigator.userLanguage;
+
+ document.querySelector('#browser-lang').innerText = 'Browser language (' + lang + ')';
+
+ var formatfieldComponent = document.querySelector('#sample2-component');
+ formatfieldComponent.querySelector('input').addEventListener('blur', function () {
+ var unformatted = document.querySelector('#sample2-unformatted');
+ unformatted.innerText = 'Unformatted: ' + formatfieldComponent.MaterialExtFormatfield.getUnformattedValue();
+ });
+ });
+ }());
+</script>
+
diff --git a/node_modules/mdl-ext/src/grid/_grid-eqjs.scss b/node_modules/mdl-ext/src/grid/_grid-eqjs.scss
new file mode 100644
index 0000000..8068b79
--- /dev/null
+++ b/node_modules/mdl-ext/src/grid/_grid-eqjs.scss
@@ -0,0 +1,321 @@
+@charset "UTF-8";
+
+/**
+ * This code is modified from Material Design Lite _grid.sass,
+ * which is Licensed under the Apache License, Version 2.0
+ * Copyright 2015 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+//////////////////////////////////////////////////////////////////////////////////
+//
+// Element queries for _grid.scss, based on: https://github.com/Snugug/eq.js
+//
+//////////////////////////////////////////////////////////////////////////////////
+
+// Use of this module requires the user to include variables from material-design-lite in hers/his main SASS module
+//@import "../../node_modules/material-design-lite/src/variables";
+.mdlext-grid {
+ display: flex;
+ flex-flow: row wrap;
+ margin: 0 auto;
+ align-items: stretch;
+
+ &.mdlext-grid--no-spacing {
+ padding: 0;
+ }
+
+ & > .mdlext-cell {
+ box-sizing: border-box;
+ }
+
+ & > .mdlext-cell--top {
+ align-self: flex-start;
+ }
+
+ & > .mdlext-cell--middle {
+ align-self: center;
+ }
+
+ & > .mdlext-cell--bottom {
+ align-self: flex-end;
+ }
+
+ & > .mdlext-cell--stretch {
+ align-self: stretch;
+ }
+
+ .mdlext-grid--no-spacing > .mdlext-cell {
+ margin: 0;
+ }
+
+ // Define order override classes.
+ @for $i from 1 through $grid-max-columns {
+ & > .mdlext-cell--order-#{$i} {
+ order: $i;
+ }
+ }
+}
+
+// Mixins for width calculation.
+@mixin _partial-size($size, $columns, $gutter) {
+ width: calc(#{(($size / $columns) * 100) + "%"} - #{$gutter});
+}
+@mixin _full-size($gutter) {
+ @include _partial-size(1, 1, $gutter);
+}
+@mixin _offset-size($size, $columns, $gutter) {
+ margin-left: calc(#{(($size / $columns) * 100) + "%"} + #{$gutter / 2});
+}
+
+@mixin _partial-size-no-spacing($size, $columns) {
+ width: #{(($size / $columns) * 100) + "%"};
+}
+@mixin _full-size-no-spacing() {
+ @include _partial-size-no-spacing(1, 1);
+}
+@mixin _offset-size-no-spacing($size, $columns) {
+ margin-left: #{(($size / $columns) * 100) + "%"};
+}
+
+
+.mdlext-grid {
+
+ @include eq-pts((
+ grid_phone: 0,
+ grid_tablet: strip-unit($grid-tablet-breakpoint),
+ grid_desktop: strip-unit($grid-desktop-breakpoint)
+ ));
+
+ ////////// Phone //////////
+ @include eq('grid_phone') {
+ padding: $grid-phone-margin - ($grid-phone-gutter / 2);
+
+ & > .mdlext-cell {
+ margin: $grid-phone-gutter / 2;
+ @include _partial-size($grid-cell-default-columns, $grid-phone-columns, $grid-phone-gutter);
+ }
+
+ & > .mdlext-cell--hide-phone {
+ display: none !important;
+ }
+
+ // Define order override classes.
+ @for $i from 1 through $grid-max-columns {
+ & > .mdlext-cell--order-#{$i}-phone.mdlext-cell--order-#{$i}-phone {
+ order: $i;
+ }
+ }
+
+ // Define partial sizes for columnNumber < totalColumns.
+ @for $i from 1 through ($grid-phone-columns - 1) {
+ & > .mdlext-cell--#{$i}-col,
+ & > .mdlext-cell--#{$i}-col-phone.mdlext-cell--#{$i}-col-phone {
+ @include _partial-size($i, $grid-phone-columns, $grid-phone-gutter);
+ }
+ }
+
+ // Define 100% for everything else.
+ @for $i from $grid-phone-columns through $grid-desktop-columns {
+ & > .mdlext-cell--#{$i}-col,
+ & > .mdlext-cell--#{$i}-col-phone.mdlext-cell--#{$i}-col-phone {
+ @include _full-size($grid-phone-gutter);
+ }
+ }
+
+ // Define valid phone offsets.
+ @for $i from 1 through ($grid-phone-columns - 1) {
+ & > .mdlext-cell--#{$i}-offset,
+ & > .mdlext-cell--#{$i}-offset-phone.mdlext-cell--#{$i}-offset-phone {
+ @include _offset-size($i, $grid-phone-columns, $grid-phone-gutter);
+ }
+ }
+
+ &.mdlext-grid--no-spacing {
+ padding: 0;
+
+ & > .mdlext-cell {
+ margin: 0;
+ @include _partial-size-no-spacing($grid-cell-default-columns, $grid-phone-columns);
+ }
+
+ // Define partial sizes for columnNumber < totalColumns.
+ @for $i from 1 through ($grid-phone-columns - 1) {
+ & > .mdlext-cell--#{$i}-col,
+ & > .mdlext-cell--#{$i}-col-phone.mdlext-cell--#{$i}-col-phone {
+ @include _partial-size-no-spacing($i, $grid-phone-columns);
+ }
+ }
+
+ // Define 100% for everything else.
+ @for $i from $grid-phone-columns through $grid-desktop-columns {
+ & > .mdlext-cell--#{$i}-col,
+ & > .mdlext-cell--#{$i}-col-phone.mdlext-cell--#{$i}-col-phone {
+ @include _full-size-no-spacing();
+ }
+ }
+
+ // Define valid phone offsets.
+ @for $i from 1 through ($grid-phone-columns - 1) {
+ & > .mdlext-cell--#{$i}-offset,
+ & > .mdlext-cell--#{$i}-offset-phone.mdlext-cell--#{$i}-offset-phone {
+ @include _offset-size-no-spacing($i, $grid-phone-columns);
+ }
+ }
+ }
+ }
+
+ ////////// Tablet //////////
+ @include eq('grid_tablet') {
+ padding: $grid-tablet-margin - ($grid-tablet-gutter / 2);
+
+ & > .mdlext-cell {
+ margin: $grid-tablet-gutter / 2;
+ @include _partial-size($grid-cell-default-columns, $grid-tablet-columns, $grid-tablet-gutter);
+ }
+
+ & > .mdlext-cell--hide-tablet {
+ display: none !important;
+ }
+
+ // Define order override classes.
+ @for $i from 1 through $grid-max-columns {
+ & > .mdlext-cell--order-#{$i}-tablet.mdlext-cell--order-#{$i}-tablet {
+ order: $i;
+ }
+ }
+
+ // Define partial sizes for columnNumber < totalColumns.
+ @for $i from 1 through ($grid-tablet-columns - 1) {
+ & > .mdlext-cell--#{$i}-col,
+ & > .mdlext-cell--#{$i}-col-tablet.mdlext-cell--#{$i}-col-tablet {
+ @include _partial-size($i, $grid-tablet-columns, $grid-tablet-gutter);
+ }
+ }
+
+ // Define 100% for everything else.
+ @for $i from $grid-tablet-columns through $grid-desktop-columns {
+ & > .mdlext-cell--#{$i}-col,
+ & > .mdlext-cell--#{$i}-col-tablet.mdlext-cell--#{$i}-col-tablet {
+ @include _full-size($grid-tablet-gutter);
+ }
+ }
+
+ // Define valid tablet offsets.
+ @for $i from 1 through ($grid-tablet-columns - 1) {
+ & > .mdlext-cell--#{$i}-offset,
+ & > .mdlext-cell--#{$i}-offset-tablet.mdlext-cell--#{$i}-offset-tablet {
+ @include _offset-size($i, $grid-tablet-columns, $grid-tablet-gutter);
+ }
+ }
+
+ &.mdlext-grid--no-spacing {
+ padding: 0;
+
+ & > .mdlext-cell {
+ margin: 0;
+ @include _partial-size-no-spacing($grid-cell-default-columns, $grid-tablet-columns);
+ }
+
+ // Define partial sizes for columnNumber < totalColumns.
+ @for $i from 1 through ($grid-tablet-columns - 1) {
+ & > .mdlext-cell--#{$i}-col,
+ & > .mdlext-cell--#{$i}-col-tablet.mdlext-cell--#{$i}-col-tablet {
+ @include _partial-size-no-spacing($i, $grid-tablet-columns);
+ }
+ }
+
+ // Define 100% for everything else.
+ @for $i from $grid-tablet-columns through $grid-desktop-columns {
+ & > .mdlext-cell--#{$i}-col,
+ & > .mdlext-cell--#{$i}-col-tablet.mdlext-cell--#{$i}-col-tablet {
+ @include _full-size-no-spacing();
+ }
+ }
+
+ // Define valid tablet offsets.
+ @for $i from 1 through ($grid-tablet-columns - 1) {
+ & > .mdlext-cell--#{$i}-offset,
+ & > .mdlext-cell--#{$i}-offset-tablet.mdlext-cell--#{$i}-offset-tablet {
+ @include _offset-size-no-spacing($i, $grid-tablet-columns);
+ }
+ }
+ }
+ }
+
+ ////////// Desktop //////////
+ @include eq('grid_desktop') {
+ padding: $grid-desktop-margin - ($grid-desktop-gutter / 2);
+
+ & > .mdlext-cell {
+ margin: $grid-desktop-gutter / 2;
+ @include _partial-size($grid-cell-default-columns, $grid-desktop-columns, $grid-desktop-gutter);
+ }
+
+ & > .mdlext-cell--hide-desktop {
+ display: none !important;
+ }
+
+ // Define order override classes.
+ @for $i from 1 through $grid-max-columns {
+ & > .mdlext-cell--order-#{$i}-desktop.mdlext-cell--order-#{$i}-desktop {
+ order: $i;
+ }
+ }
+
+ // Define partial sizes for all numbers of columns.
+ @for $i from 1 through $grid-desktop-columns {
+ & > .mdlext-cell--#{$i}-col,
+ & > .mdlext-cell--#{$i}-col-desktop.mdlext-cell--#{$i}-col-desktop {
+ @include _partial-size($i, $grid-desktop-columns, $grid-desktop-gutter);
+ }
+ }
+
+ // Define valid desktop offsets.
+ @for $i from 1 through ($grid-desktop-columns - 1) {
+ & > .mdlext-cell--#{$i}-offset,
+ & > .mdlext-cell--#{$i}-offset-desktop.mdlext-cell--#{$i}-offset-desktop {
+ @include _offset-size($i, $grid-desktop-columns, $grid-desktop-gutter);
+ }
+ }
+
+ &.mdlext-grid--no-spacing {
+ padding: 0;
+
+ & > .mdlext-cell {
+ margin: 0;
+ @include _partial-size-no-spacing($grid-cell-default-columns, $grid-desktop-columns);
+ }
+
+ // Define partial sizes for all numbers of columns.
+ @for $i from 1 through $grid-desktop-columns {
+ & > .mdlext-cell--#{$i}-col,
+ & > .mdlext-cell--#{$i}-col-desktop.mdlext-cell--#{$i}-col-desktop {
+ @include _partial-size-no-spacing($i, $grid-desktop-columns);
+ }
+ }
+
+ // Define valid desktop offsets.
+ @for $i from 1 through ($grid-desktop-columns - 1) {
+ & > .mdlext-cell--#{$i}-offset,
+ & > .mdlext-cell--#{$i}-offset-desktop.mdlext-cell--#{$i}-offset-desktop {
+ @include _offset-size-no-spacing($i, $grid-desktop-columns);
+ }
+ }
+ }
+ }
+}
+
+@include eq-selectors;
diff --git a/node_modules/mdl-ext/src/grid/_grid-media-queries.scss b/node_modules/mdl-ext/src/grid/_grid-media-queries.scss
new file mode 100644
index 0000000..c942ff1
--- /dev/null
+++ b/node_modules/mdl-ext/src/grid/_grid-media-queries.scss
@@ -0,0 +1,238 @@
+@charset "UTF-8";
+
+/**
+ * This code is modified from Material Design Lite _grid.sass,
+ * which is Licensed under the Apache License, Version 2.0
+ * Copyright 2015 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+///////////////////////////////////////////////////////////////////////
+//
+// Grid media queries, modified from Material Design Lite _grid.sass
+//
+///////////////////////////////////////////////////////////////////////
+// Use of this module requires the user to include variables from material-design-lite in hers/his main SASS module
+//@import "../../node_modules/material-design-lite/src/variables";
+
+
+.mdlext-grid {
+ display: flex;
+ flex-flow: row wrap;
+ margin: 0 auto;
+ align-items: stretch;
+
+ &.mdlext-grid--no-spacing {
+ padding: 0;
+ }
+}
+
+.mdlext-cell {
+ box-sizing: border-box;
+}
+
+
+.mdlext-cell--top {
+ align-self: flex-start;
+}
+
+.mdlext-cell--middle {
+ align-self: center;
+}
+
+.mdlext-cell--bottom {
+ align-self: flex-end;
+}
+
+.mdlext-cell--stretch {
+ align-self: stretch;
+}
+
+.mdlext-grid.mdlext-grid--no-spacing > .mdlext-cell {
+ margin: 0;
+}
+
+// Define order override classes.
+@for $i from 1 through $grid-max-columns {
+ .mdlext-cell--order-#{$i} {
+ order: $i;
+ }
+}
+
+
+// Mixins for width calculation.
+@mixin partial-size($size, $columns, $gutter) {
+ width: calc(#{(($size / $columns) * 100) + "%"} - #{$gutter});
+
+ .mdlext-grid--no-spacing > & {
+ width: #{(($size / $columns) * 100) + "%"};
+ }
+}
+
+@mixin full-size($gutter) {
+ @include partial-size(1, 1, $gutter);
+}
+
+@mixin offset-size($size, $columns, $gutter) {
+ margin-left: calc(#{(($size / $columns) * 100) + "%"} + #{$gutter / 2});
+
+ .mdlext-grid.mdlext-grid--no-spacing > & {
+ margin-left: #{(($size / $columns) * 100) + "%"};
+ }
+}
+
+
+
+////////// Phone //////////
+
+/* stylelint-disable */
+@media (max-width: $grid-tablet-breakpoint - 1) {
+/* stylelint-enable */
+ .mdlext-grid {
+ padding: $grid-phone-margin - ($grid-phone-gutter / 2);
+ }
+
+ .mdlext-cell {
+ margin: $grid-phone-gutter / 2;
+ @include partial-size($grid-cell-default-columns, $grid-phone-columns, $grid-phone-gutter);
+ }
+
+ .mdlext-cell--hide-phone {
+ display: none !important;
+ }
+
+ // Define order override classes.
+ @for $i from 1 through $grid-max-columns {
+ .mdlext-cell--order-#{$i}-phone.mdlext-cell--order-#{$i}-phone {
+ order: $i;
+ }
+ }
+
+ // Define partial sizes for columnNumber < totalColumns.
+ @for $i from 1 through ($grid-phone-columns - 1) {
+ .mdlext-cell--#{$i}-col,
+ .mdlext-cell--#{$i}-col-phone.mdlext-cell--#{$i}-col-phone {
+ @include partial-size($i, $grid-phone-columns, $grid-phone-gutter);
+ }
+ }
+
+ // Define 100% for everything else.
+ @for $i from $grid-phone-columns through $grid-desktop-columns {
+ .mdlext-cell--#{$i}-col,
+ .mdlext-cell--#{$i}-col-phone.mdlext-cell--#{$i}-col-phone {
+ @include full-size($grid-phone-gutter);
+ }
+ }
+
+ // Define valid phone offsets.
+ @for $i from 1 through ($grid-phone-columns - 1) {
+ .mdlext-cell--#{$i}-offset,
+ .mdlext-cell--#{$i}-offset-phone.mdlext-cell--#{$i}-offset-phone {
+ @include offset-size($i, $grid-phone-columns, $grid-phone-gutter);
+ }
+ }
+}
+
+
+////////// Tablet //////////
+
+/* stylelint-disable */
+@media (min-width: $grid-tablet-breakpoint) and (max-width: $grid-desktop-breakpoint - 1) { /* stylelint-enable */
+ .mdlext-grid {
+ padding: $grid-tablet-margin - ($grid-tablet-gutter / 2);
+ }
+
+ .mdlext-cell {
+ margin: $grid-tablet-gutter / 2;
+ @include partial-size($grid-cell-default-columns, $grid-tablet-columns, $grid-tablet-gutter);
+ }
+
+ .mdlext-cell--hide-tablet {
+ display: none !important;
+ }
+
+ // Define order override classes.
+ @for $i from 1 through $grid-max-columns {
+ .mdlext-cell--order-#{$i}-tablet.mdlext-cell--order-#{$i}-tablet {
+ order: $i;
+ }
+ }
+
+ // Define partial sizes for columnNumber < totalColumns.
+ @for $i from 1 through ($grid-tablet-columns - 1) {
+ .mdlext-cell--#{$i}-col,
+ .mdlext-cell--#{$i}-col-tablet.mdlext-cell--#{$i}-col-tablet {
+ @include partial-size($i, $grid-tablet-columns, $grid-tablet-gutter);
+ }
+ }
+
+ // Define 100% for everything else.
+ @for $i from $grid-tablet-columns through $grid-desktop-columns {
+ .mdlext-cell--#{$i}-col,
+ .mdlext-cell--#{$i}-col-tablet.mdlext-cell--#{$i}-col-tablet {
+ @include full-size($grid-tablet-gutter);
+ }
+ }
+
+ // Define valid tablet offsets.
+ @for $i from 1 through ($grid-tablet-columns - 1) {
+ .mdlext-cell--#{$i}-offset,
+ .mdlext-cell--#{$i}-offset-tablet.mdlext-cell--#{$i}-offset-tablet {
+ @include offset-size($i, $grid-tablet-columns, $grid-tablet-gutter);
+ }
+ }
+}
+
+
+////////// Desktop //////////
+
+@media (min-width: $grid-desktop-breakpoint) {
+ .mdlext-grid {
+ padding: $grid-desktop-margin - ($grid-desktop-gutter / 2);
+ }
+
+ .mdlext-cell {
+ margin: $grid-desktop-gutter / 2;
+ @include partial-size($grid-cell-default-columns, $grid-desktop-columns, $grid-desktop-gutter);
+ }
+
+ .mdlext-cell--hide-desktop {
+ display: none !important;
+ }
+
+ // Define order override classes.
+ @for $i from 1 through $grid-max-columns {
+ .mdlext-cell--order-#{$i}-desktop.mdlext-cell--order-#{$i}-desktop {
+ order: $i;
+ }
+ }
+
+ // Define partial sizes for all numbers of columns.
+ @for $i from 1 through $grid-desktop-columns {
+ .mdlext-cell--#{$i}-col,
+ .mdlext-cell--#{$i}-col-desktop.mdlext-cell--#{$i}-col-desktop {
+ @include partial-size($i, $grid-desktop-columns, $grid-desktop-gutter);
+ }
+ }
+
+ // Define valid desktop offsets.
+ @for $i from 1 through ($grid-desktop-columns - 1) {
+ .mdlext-cell--#{$i}-offset,
+ .mdlext-cell--#{$i}-offset-desktop.mdlext-cell--#{$i}-offset-desktop {
+ @include offset-size($i, $grid-desktop-columns, $grid-desktop-gutter);
+ }
+ }
+}
+
diff --git a/node_modules/mdl-ext/src/grid/readme.md b/node_modules/mdl-ext/src/grid/readme.md
new file mode 100644
index 0000000..569e7c8
--- /dev/null
+++ b/node_modules/mdl-ext/src/grid/readme.md
@@ -0,0 +1,52 @@
+# Grid
+
+![Grid](../../etc/grid.png)
+
+A responsive **grid** based on **element queries** in favour of media queries.
+
+## Introduction
+Grids provide users with a way to view content in an organized manner that might otherwise be difficult to
+understand or retain. Their design and use is an important factor in the overall user experience.
+
+The Material Design Lite Ext (MDLEXT) grid has two versions; one version based on media queries and one version
+based on **element queries**. The MDLEXT grid is a copy of the
+[Material Design Lite grid](https://github.com/google/material-design-lite/tree/master/src/grid) - with additional
+element queries support to distribute grid cells in a more responsive fashion.
+
+### How to use the eq.js version of MDLEXT grid
+
+ 1. Install [eq.js](https://github.com/Snugug/eq.js).
+```sh
+$ npm install --save eq.js
+```
+
+ 2. Import `mdl-ext-eqjs.scss` in your main SASS file. Remove `mdl-ext.scss` - they can not co exist.
+```css
+@import '../node_modules/mdl-ext/src/mdl-ext-eqjs';
+```
+
+ 3. Import or Require `eq.js`.
+```javascript
+const eqjs = require('eq.js'); // ... or: import eqjs from 'eq.js';
+```
+
+ 4. Optionally trigger `eq.js`<br/>
+If you're loading html fragments using e.g. Ajax, then trigger `eq.js` after page load.
+
+```javascript
+window.fetch(href, {method: 'get'})
+ .then(response => response.text())
+ .then(text => {
+ contentPanelEl.insertAdjacentHTML('afterbegin', text);
+
+ // Trigger eq.js
+ eqjs.refreshNodes();
+ eqjs.query(undefined, true);
+})
+.catch(err => console.error(err));
+```
+
+An example of how to use `eq.js` in a SPA can be found [here](https://github.com/leifoolsen/mdl-webpack).
+
+## To include a MDLEXT **grid** component:
+Folow the documention for the [original mdl-grid](https://github.com/google/material-design-lite/blob/master/src/grid/README.md#to-include-an-mdl-grid-component). Just replace `mdl-` with `mdlext-`, and you're good to go.
diff --git a/node_modules/mdl-ext/src/grid/snippets/grid.html b/node_modules/mdl-ext/src/grid/snippets/grid.html
new file mode 100644
index 0000000..26e6b11
--- /dev/null
+++ b/node_modules/mdl-ext/src/grid/snippets/grid.html
@@ -0,0 +1,121 @@
+<p>Element queries vs Media Queries. Drag the slider to see the effect</p>
+
+<style>
+
+ .demo-grid {
+ margin-bottom: 16px;
+ }
+ .demo-grid .mdl-grid,
+ .demo-grid .mdlext-grid {
+ /*padding: 0;*/
+ }
+ .demo-grid .mdl-cell,
+ .demo-grid .mdlext-cell {
+ background: rgb(63,81,181);
+ text-align: center;
+ color: white;
+ padding: 10px;
+ border: 1px solid #aaaaaa;
+ }
+ .demo-grid .mdl-cell:nth-child(odd),
+ .demo-grid .mdlext-cell:nth-child(odd) {
+ background: rgb(33,150,243);
+ }
+ .demo-grid-c .mdl-cell,
+ .demo-grid-c .mdlext-cell {
+ background: rgb(255,213,79);
+ color: #000;
+ border: 0;
+ }
+ .demo-grid-c .mdl-cell:nth-child(odd),
+ .demo-grid-c .mdlext-cell:nth-child(odd) {
+ background: rgb(165,214,167);
+ color: #000;
+ }
+</style>
+
+
+<p id="grid-container-width" style="text-align: center;">
+ <strong>100</strong>%
+ <input class="mdl-slider mdl-js-slider" type="range" min="50" max="100" value="100" step="10" tabindex="0">
+</p>
+
+<div style="border: 1px solid #dddddd;">
+ <div id="grid-container" style="margin: 0 auto;">
+
+ <h5>mdlext-grid, using element queries</h5>
+ <div class="demo-grid">
+ <div class="mdlext-grid mdlext-grid--no-spacing">
+ <div class="mdlext-cell mdlext-cell--1-col">1</div>
+ <div class="mdlext-cell mdlext-cell--1-col">1</div>
+ <div class="mdlext-cell mdlext-cell--1-col">1</div>
+ <div class="mdlext-cell mdlext-cell--1-col">1</div>
+ <div class="mdlext-cell mdlext-cell--1-col">1</div>
+ <div class="mdlext-cell mdlext-cell--1-col">1</div>
+ <div class="mdlext-cell mdlext-cell--1-col">1</div>
+ <div class="mdlext-cell mdlext-cell--1-col">1</div>
+ <div class="mdlext-cell mdlext-cell--1-col">1</div>
+ <div class="mdlext-cell mdlext-cell--1-col">1</div>
+ <div class="mdlext-cell mdlext-cell--1-col">1</div>
+ <div class="mdlext-cell mdlext-cell--1-col">1</div>
+ </div>
+ </div>
+
+ <div class="demo-grid demo-grid-c">
+ <div class="mdlext-grid mdlext-grid--no-spacing">
+ <div class="mdlext-cell mdlext-cell--4-col mdlext-cell--2-col-tablet mdlext-cell--1-col-phone">4 (2 tablet, 1 phone)</div>
+ <div class="mdlext-cell mdlext-cell--6-col mdlext-cell--4-col-tablet mdlext-cell--3-col-phone">6 (4 tablet, 3 phone)</div>
+ <div class="mdlext-cell mdlext-cell--2-col mdlext-cell--2-col-tablet mdlext-cell--hide-phone">2 (2 tablet, hide phone)</div>
+ </div>
+ </div>
+
+
+ <h5>mdl-grid, using media queries</h5>
+ <div class="demo-grid">
+ <div class="mdl-grid mdl-grid--no-spacing">
+ <div class="mdl-cell mdl-cell--1-col">1</div>
+ <div class="mdl-cell mdl-cell--1-col">1</div>
+ <div class="mdl-cell mdl-cell--1-col">1</div>
+ <div class="mdl-cell mdl-cell--1-col">1</div>
+ <div class="mdl-cell mdl-cell--1-col">1</div>
+ <div class="mdl-cell mdl-cell--1-col">1</div>
+ <div class="mdl-cell mdl-cell--1-col">1</div>
+ <div class="mdl-cell mdl-cell--1-col">1</div>
+ <div class="mdl-cell mdl-cell--1-col">1</div>
+ <div class="mdl-cell mdl-cell--1-col">1</div>
+ <div class="mdl-cell mdl-cell--1-col">1</div>
+ <div class="mdl-cell mdl-cell--1-col">1</div>
+ </div>
+ </div>
+
+ <div class="demo-grid demo-grid-c">
+ <div class="mdl-grid mdl-grid--no-spacing">
+ <div class="mdl-cell mdl-cell--4-col mdl-cell--2-col-tablet mdl-cell--1-col-phone">4 (2 tablet, 1 phone)</div>
+ <div class="mdl-cell mdl-cell--6-col mdl-cell--4-col-tablet mdl-cell--3-col-phone">6 (4 tablet, 3 phone)</div>
+ <div class="mdl-cell mdl-cell--2-col mdl-cell--2-col-tablet mdl-cell--hide-phone">2 (2 tablet, hide phone)</div>
+ </div>
+ </div>
+ </div>
+</div>
+
+<script>
+ 'use strict';
+ window.addEventListener('load', function() {
+ (function() {
+ 'use strict';
+ var widthLabel = document.querySelector('#grid-container-width strong');
+ var slider = document.querySelector('#grid-container-width input');
+
+ slider.addEventListener('input', function(e) {
+ setWidth(this.value);
+ }.bind(slider));
+
+ function setWidth(value) {
+ widthLabel.innerText = value;
+ document.querySelector('#grid-container').style.width = value + '%';
+ eqjs.refreshNodes();
+ eqjs.query(undefined, true);
+ }
+ }());
+ });
+</script>
diff --git a/node_modules/mdl-ext/src/index.js b/node_modules/mdl-ext/src/index.js
new file mode 100644
index 0000000..b6fa845
--- /dev/null
+++ b/node_modules/mdl-ext/src/index.js
@@ -0,0 +1,10 @@
+import './utils';
+import './accordion/accordion';
+import './collapsible/collapsible';
+import './carousel/carousel';
+import './lightboard/lightboard';
+import './lightbox/lightbox';
+import './menu-button/menu-button';
+import './selectfield/selectfield';
+import './formatfield/formatfield';
+import './sticky-header/sticky-header';
diff --git a/node_modules/mdl-ext/src/lightboard/_lightboard-eqjs.scss b/node_modules/mdl-ext/src/lightboard/_lightboard-eqjs.scss
new file mode 100644
index 0000000..7d2666b
--- /dev/null
+++ b/node_modules/mdl-ext/src/lightboard/_lightboard-eqjs.scss
@@ -0,0 +1,110 @@
+@charset "UTF-8";
+//////////////////////////////////////////////////////////////////////////////////
+//
+// Element queries for _lightbox.scss, based on: https://github.com/Snugug/eq.js
+//
+//////////////////////////////////////////////////////////////////////////////////
+
+@import "../variables";
+@import "../functions";
+
+.mdlext-lightboard {
+
+ @include eq-pts((
+ lightboard_medium_small: strip-unit($mdlext-lightboard-medium-small-breakpoint),
+ lightboard_medium: strip-unit($mdlext-lightboard-medium-breakpoint),
+ lightboard_medium_large: strip-unit($mdlext-lightboard-medium-large-breakpoint),
+ lightboard_large: strip-unit($mdlext-lightboard-large-breakpoint)
+ ));
+
+ ////// small - meduim-small //////
+ @include eq('lightboard_medium_small') {
+ padding: calc((#{$mdlext-lightboard-medium-small-margin} - #{$mdlext-lightboard-medium-small-gutter}) / 2);
+
+ .mdlext-lightboard__slide {
+ margin: calc(#{$mdlext-lightboard-medium-small-gutter} / 2);
+ width: calc(1 / #{$mdlext-lightboard-medium-small-columns} * 100% - #{$mdlext-lightboard-medium-small-gutter});
+
+ .mdlext-lightboard__slide__frame figure {
+ margin: $mdlext-lightboard-medium-small-frame-width;
+ }
+ }
+ &.mdlext-lightboard--no-spacing {
+ padding: 0;
+
+ .mdlext-lightboard__slide {
+ margin: 0;
+ width: calc(1 / #{$mdlext-lightboard-medium-small-columns} * 100%);
+ }
+ }
+ }
+
+ ////// meduim-small - medium //////
+ @include eq('lightboard_medium') {
+ padding: calc((#{$mdlext-lightboard-medium-margin} - #{$mdlext-lightboard-medium-gutter}) / 2);
+
+ .mdlext-lightboard__slide {
+ margin: calc(#{$mdlext-lightboard-medium-gutter} / 2);
+ width: calc(1 / #{$mdlext-lightboard-medium-columns} * 100% - #{$mdlext-lightboard-medium-gutter});
+
+ .mdlext-lightboard__slide__frame figure {
+ margin: $mdlext-lightboard-medium-frame-width;
+ }
+ }
+ &.mdlext-lightboard--no-spacing {
+ padding: 0;
+
+ .mdlext-lightboard__slide {
+ margin: 0;
+ width: calc(1 / #{$mdlext-lightboard-medium-columns} * 100%);
+ }
+ }
+ }
+
+ ////// meduim - medium-large //////
+ @include eq('lightboard_medium_large') {
+ padding: calc((#{$mdlext-lightboard-medium-large-margin} - #{$mdlext-lightboard-medium-large-gutter}) / 2);
+
+ .mdlext-lightboard__slide {
+ margin: calc(#{$mdlext-lightboard-medium-large-gutter} / 2);
+ width: calc(1 / #{$mdlext-lightboard-medium-large-columns} * 100% - #{$mdlext-lightboard-medium-large-gutter});
+
+ .mdlext-lightboard__slide__frame figure {
+ margin: $mdlext-lightboard-medium-large-frame-width;
+ }
+ }
+ &.mdlext-lightboard--no-spacing {
+ padding: 0;
+
+ .mdlext-lightboard__slide {
+ margin: 0;
+ width: calc(1 / #{$mdlext-lightboard-medium-large-columns} * 100%);
+ }
+ }
+ }
+
+ ////// meduim-large - large //////
+ @include eq('lightboard_large') {
+ padding: calc((#{$mdlext-lightboard-large-margin} - #{$mdlext-lightboard-large-gutter}) / 2);
+
+ .mdlext-lightboard__slide {
+ margin: calc(#{$mdlext-lightboard-large-gutter} / 2);
+ width: calc(1 / #{$mdlext-lightboard-large-columns} * 100% - #{$mdlext-lightboard-large-gutter});
+
+ .mdlext-lightboard__slide__frame figure {
+ margin: $mdlext-lightboard-large-frame-width;
+ }
+ }
+ &.mdlext-lightboard--no-spacing {
+ padding: 0;
+
+ .mdlext-lightboard__slide {
+ margin: 0;
+ width: calc(1 / #{$mdlext-lightboard-large-columns} * 100%);
+ }
+ }
+ }
+}
+
+@include eq-selectors;
+
diff --git a/node_modules/mdl-ext/src/lightboard/_lightboard-media-queries.scss b/node_modules/mdl-ext/src/lightboard/_lightboard-media-queries.scss
new file mode 100644
index 0000000..b87f830
--- /dev/null
+++ b/node_modules/mdl-ext/src/lightboard/_lightboard-media-queries.scss
@@ -0,0 +1,113 @@
+@charset "UTF-8";
+
+//////////////////////////////
+//
+// Lightboard media queries
+//
+//////////////////////////////
+@import "../variables";
+
+////////// Small /////////////
+//@media (max-width: $mdlext-lightboard-medium-small-breakpoint - 1) {
+// // This is the default, see: _lightboard.scss
+//}
+
+////////// Medium small //////////
+/* stylelint-disable */
+@media (min-width: $mdlext-lightboard-medium-small-breakpoint) and (max-width: $mdlext-lightboard-medium-breakpoint - 1) { /* stylelint-enable */
+ .mdlext-lightboard {
+ padding: calc((#{$mdlext-lightboard-medium-small-margin} - #{$mdlext-lightboard-medium-small-gutter}) / 2);
+
+ .mdlext-lightboard__slide {
+ margin: calc(#{$mdlext-lightboard-medium-small-gutter} / 2);
+ width: calc(1 / #{$mdlext-lightboard-medium-small-columns} * 100% - #{$mdlext-lightboard-medium-small-gutter});
+
+ .mdlext-lightboard__slide__frame figure {
+ margin: $mdlext-lightboard-medium-small-frame-width;
+ }
+ }
+ &.mdlext-lightboard--no-spacing {
+ padding: 0;
+
+ .mdlext-lightboard__slide {
+ margin: 0;
+ width: calc(1 / #{$mdlext-lightboard-medium-small-columns} * 100%);
+ }
+ }
+ }
+}
+
+////////// Medium //////////
+/* stylelint-disable */
+@media (min-width: $mdlext-lightboard-medium-breakpoint) and (max-width: $mdlext-lightboard-medium-large-breakpoint - 1) { /* stylelint-enable */
+ .mdlext-lightboard {
+ padding: calc((#{$mdlext-lightboard-medium-margin} - #{$mdlext-lightboard-medium-gutter}) / 2);
+
+ .mdlext-lightboard__slide {
+ margin: calc(#{$mdlext-lightboard-medium-gutter} / 2);
+ width: calc(1 / #{$mdlext-lightboard-medium-columns} * 100% - #{$mdlext-lightboard-medium-gutter});
+
+ .mdlext-lightboard__slide__frame figure {
+ margin: $mdlext-lightboard-medium-frame-width;
+ }
+ }
+ &.mdlext-lightboard--no-spacing {
+ padding: 0;
+
+ .mdlext-lightboard__slide {
+ margin: 0;
+ width: calc(1 / #{$mdlext-lightboard-medium-columns} * 100%);
+ }
+ }
+ }
+}
+
+////////// Medium large //////////
+/* stylelint-disable */
+@media (min-width: $mdlext-lightboard-medium-large-breakpoint) and (max-width: $mdlext-lightboard-large-breakpoint - 1) { /* stylelint-enable */
+ .mdlext-lightboard {
+ padding: calc((#{$mdlext-lightboard-medium-large-margin} - #{$mdlext-lightboard-medium-large-gutter}) / 2);
+
+ .mdlext-lightboard__slide {
+ margin: calc(#{$mdlext-lightboard-medium-large-gutter} / 2);
+ width: calc(1 / #{$mdlext-lightboard-medium-large-columns} * 100% - #{$mdlext-lightboard-medium-large-gutter});
+
+ .mdlext-lightboard__slide__frame figure {
+ margin: $mdlext-lightboard-medium-large-frame-width;
+ }
+ }
+ &.mdlext-lightboard--no-spacing {
+ padding: 0;
+
+ .mdlext-lightboard__slide {
+ margin: 0;
+ width: calc(1 / #{$mdlext-lightboard-medium-large-columns} * 100%);
+ }
+ }
+ }
+}
+
+////////// Large //////////
+@media (min-width: $mdlext-lightboard-large-breakpoint) {
+ .mdlext-lightboard {
+ padding: calc((#{$mdlext-lightboard-large-margin} - #{$mdlext-lightboard-large-gutter}) / 2);
+
+ .mdlext-lightboard__slide {
+ margin: calc(#{$mdlext-lightboard-large-gutter} / 2);
+ width: calc(1 / #{$mdlext-lightboard-large-columns} * 100% - #{$mdlext-lightboard-large-gutter});
+
+ .mdlext-lightboard__slide__frame figure {
+ margin: $mdlext-lightboard-large-frame-width;
+ }
+ }
+ &.mdlext-lightboard--no-spacing {
+ padding: 0;
+
+ .mdlext-lightboard__slide {
+ margin: 0;
+ width: calc(1 / #{$mdlext-lightboard-large-columns} * 100%);
+ }
+ }
+ }
+}
+
diff --git a/node_modules/mdl-ext/src/lightboard/_lightboard.scss b/node_modules/mdl-ext/src/lightboard/_lightboard.scss
new file mode 100644
index 0000000..775d283
--- /dev/null
+++ b/node_modules/mdl-ext/src/lightboard/_lightboard.scss
@@ -0,0 +1,178 @@
+@charset "UTF-8";
+
+/**
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * A lightboard is a translucent surface illuminated from behind, used for situations
+ * where a shape laid upon the surface needs to be seen with high contrast. In the "old days" of photography
+ * photograpers used a lightboard to get a quick view of their slides. The goal is to create a responsive lightbox
+ * design, based on flex layout, similar to what is used in Adobe LightRoom to browse images.
+ */
+
+// Use of this module requires the user to include variables from material-design-lite
+//@import "../../node_modules/material-design-lite/src/variables";
+//@import "../../node_modules/material-design-lite/src/mixins";
+@import "../variables";
+
+ul.mdlext-lightboard {
+ list-style: none;
+}
+
+.mdlext-lightboard {
+ box-sizing: border-box;
+ margin: 0 auto;
+ padding: 0;
+ display: flex;
+ flex-flow:row wrap;
+ align-items: stretch;
+
+ *,
+ *::before,
+ *::after,
+ input[type="search"] {
+ box-sizing: border-box;
+ }
+
+ .mdlext-lightboard__slide {
+ background-color: $mdlext-lightboard-slide-background-color;
+ border: 1px solid $mdlext-lightboard-slide-border-color;
+ border-radius: $mdlext-lightboard-slide-border-radius;
+ box-shadow: $mdlext-lightboard-slide-box-shadow;
+ position: relative;
+ display: block;
+ max-width: $mdlext-lightboard-slide-max-size;
+
+ &::before {
+ // 1:1 ratio
+ // TODO: Use a class for ratio so the grid can display slides with different ratios (16:9, 16:10, 4:3 ...)
+ content: '';
+ display: block;
+ padding-top: 100%;
+ }
+ &:hover,
+ &:active,
+ &:focus {
+ border-color: $mdlext-lightboard-slide-border-color-hover;
+ background-color: $mdlext-lightboard-slide-background-color-hover;
+ box-shadow: $mdlext-lightboard-slide-box-shadow-hover;
+
+ figcaption {
+ color: rgba(0, 0, 0, 1) !important;
+ background-color: rgba(255, 255, 255, 0.2);
+ }
+ }
+ &:focus {
+ outline-offset: -2px;
+ outline-color: $mdlext-lightboard-focus-outline-color;
+ }
+ &[aria-selected='true'] {
+ background-color: $mdlext-lightboard-slide-active-bacground-color;
+
+ figcaption {
+ color: rgba(0, 0, 0, 1) !important;
+ background-color: rgba(255, 255, 255, 0.2);
+ }
+ }
+ &__frame,
+ &__ripple-container {
+ text-decoration: none;
+ display: block;
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+
+ &:focus {
+ outline-offset: -2px;
+ outline-color: $mdlext-lightboard-focus-outline-color;
+ }
+ & .mdl-ripple {
+ background: $mdlext-lightboard-ripple-color;
+ }
+ figure {
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+
+ img {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ margin: auto;
+ max-width: 100%;
+ max-height: 100%;
+ border-width: 0;
+ border-radius: $mdlext-lightboard-slide-inner-border-radius;
+ }
+ figcaption {
+ @include typo-caption($colorContrast: false, $usePreferred: true);
+
+ color: $mdlext-lightboard-figcaption-text-color;
+ position: absolute;
+ bottom: -2px;
+ white-space: nowrap;
+ overflow: hidden;
+ max-width: 100%;
+ width: 100%;
+ text-align: center;
+ text-overflow: ellipsis;
+ padding: 4px 0;
+ }
+ }
+ &:hover {
+ figcaption {
+ // As far as I can see there is no way to darken/lighten a text color
+ // defined by MDL, due to the "unqote" functions.
+ // So this is a hack
+ color: rgba(0, 0, 0, 1) !important;
+ background-color: rgba(255, 255, 255, 0.2);
+ }
+ }
+ }
+ }
+}
+
+////// Media / Element queries default, Small //////
+.mdlext-lightboard {
+ padding: calc((#{$mdlext-lightboard-small-margin} - #{$mdlext-lightboard-small-gutter}) / 2);
+
+ .mdlext-lightboard__slide {
+ margin: calc(#{$mdlext-lightboard-small-gutter} / 2);
+ width: calc(1 / #{$mdlext-lightboard-small-columns} * 100% - #{$mdlext-lightboard-small-gutter});
+
+ .mdlext-lightboard__slide__frame figure {
+ margin: $mdlext-lightboard-small-frame-width;
+ }
+ }
+ &.mdlext-lightboard--no-spacing {
+ padding: 0;
+
+ .mdlext-lightboard__slide {
+ margin: 0;
+ width: calc(1 / #{$mdlext-lightboard-small-columns} * 100%);
+ }
+ }
+}
+
+// Import one of _lightboard-media-queries.scss or _lightboard-eq-js.scss to complete SASS
diff --git a/node_modules/mdl-ext/src/lightboard/lightboard.js b/node_modules/mdl-ext/src/lightboard/lightboard.js
new file mode 100644
index 0000000..9a49559
--- /dev/null
+++ b/node_modules/mdl-ext/src/lightboard/lightboard.js
@@ -0,0 +1,332 @@
+/**
+ * @license
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+/**
+ * A lightboard is a translucent surface illuminated from behind, used for situations
+ * where a shape laid upon the surface needs to be seen with high contrast. In the "old days" of photography
+ * photograpers used a lightboard to get a quick view of their slides. The goal is to create a responsive lightbox
+ * design, based on flex layout, similar to what is used in Adobe LightRoom to browse images.
+ */
+
+import {
+ VK_ENTER,
+ VK_SPACE,
+ VK_END,
+ VK_HOME,
+ VK_ARROW_LEFT,
+ VK_ARROW_UP,
+ VK_ARROW_RIGHT,
+ VK_ARROW_DOWN,
+ IS_UPGRADED,
+ MDL_RIPPLE,
+ MDL_RIPPLE_COMPONENT,
+ MDL_RIPPLE_EFFECT,
+ MDL_RIPPLE_EFFECT_IGNORE_EVENTS
+} from '../utils/constants';
+
+const MDL_RIPPLE_CONTAINER = 'mdlext-lightboard__slide__ripple-container';
+
+(function() {
+ 'use strict';
+
+ //const LIGHTBOARD = 'mdlext-lightboard';
+ const LIGHTBOARD_ROLE = 'grid';
+ const SLIDE = 'mdlext-lightboard__slide';
+ const SLIDE_ROLE = 'gridcell';
+ const SLIDE_TABSTOP = 'mdlext-lightboard__slide__frame';
+ /**
+ * @constructor
+ * @param {Element} element The element that will be upgraded.
+ */
+ const MaterialExtLightboard = function MaterialExtLightboard(element) {
+ // Stores the element.
+ this.element_ = element;
+
+ // Initialize instance.
+ this.init();
+ };
+ window['MaterialExtLightboard'] = MaterialExtLightboard;
+
+
+ // Helpers
+ const getSlide = element => {
+ return element ? element.closest(`.${SLIDE}`) : null;
+ };
+
+
+
+ // Private methods.
+
+ /**
+ * Select a slide, i.e. set aria-selected="true"
+ * @param element
+ * @private
+ */
+ MaterialExtLightboard.prototype.selectSlide_ = function(element) {
+ const slide = getSlide(element);
+ if( slide && !slide.hasAttribute('aria-selected') ) {
+ [...this.element_.querySelectorAll(`.${SLIDE}[aria-selected="true"]`)]
+ .forEach(selectedSlide => selectedSlide.removeAttribute('aria-selected'));
+
+ slide.setAttribute('aria-selected', 'true');
+ }
+ };
+
+
+ /**
+ * Dispatch select event
+ * @param {Element} slide The slide that caused the event
+ * @private
+ */
+ MaterialExtLightboard.prototype.dispatchSelectEvent_ = function ( slide ) {
+ this.element_.dispatchEvent(
+ new CustomEvent('select', {
+ bubbles: true,
+ cancelable: true,
+ detail: { source: slide }
+ })
+ );
+ };
+
+ /**
+ * Handles custom command event, 'first', 'next', 'prev', 'last', 'select' or upgrade
+ * @param event. A custom event
+ * @private
+ */
+ MaterialExtLightboard.prototype.commandHandler_ = function( event ) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ if(event && event.detail) {
+ this.command(event.detail);
+ }
+ };
+
+
+ // Public methods
+
+ /**
+ * Initialize lightboard slides
+ * @public
+ */
+ MaterialExtLightboard.prototype.upgradeSlides = function() {
+
+ const addRipple = slide => {
+ // Use slide frame as ripple container
+ if(!slide.querySelector(`.${MDL_RIPPLE_CONTAINER}`)) {
+ const a = slide.querySelector(`.${SLIDE_TABSTOP}`);
+ if(a) {
+ const rippleContainer = a;
+ rippleContainer.classList.add(MDL_RIPPLE_CONTAINER);
+ rippleContainer.classList.add(MDL_RIPPLE_EFFECT);
+ const ripple = document.createElement('span');
+ ripple.classList.add(MDL_RIPPLE);
+ rippleContainer.appendChild(ripple);
+ componentHandler.upgradeElement(rippleContainer, MDL_RIPPLE_COMPONENT);
+ }
+ }
+ };
+
+ const hasRippleEffect = this.element_.classList.contains(MDL_RIPPLE_EFFECT);
+
+ [...this.element_.querySelectorAll(`.${SLIDE}`)].forEach( slide => {
+
+ slide.setAttribute('role', SLIDE_ROLE);
+
+ if(!slide.querySelector('a')) {
+ slide.setAttribute('tabindex', '0');
+ }
+ if(hasRippleEffect) {
+ addRipple(slide);
+ }
+ });
+ };
+ MaterialExtLightboard.prototype['upgradeSlides'] = MaterialExtLightboard.prototype.upgradeSlides;
+
+
+ /**
+ * Execute command
+ * @param detail
+ * @public
+ */
+ MaterialExtLightboard.prototype.command = function( detail ) {
+
+ const firstSlide = () => {
+ return this.element_.querySelector(`.${SLIDE}:first-child`);
+ };
+
+ const lastSlide = () => {
+ return this.element_.querySelector(`.${SLIDE}:last-child`);
+ };
+
+ const nextSlide = () => {
+ const slide = this.element_.querySelector(`.${SLIDE}[aria-selected="true"]`).nextElementSibling;
+ return slide ? slide : firstSlide();
+ };
+
+ const prevSlide = () => {
+ const slide = this.element_.querySelector(`.${SLIDE}[aria-selected="true"]`).previousElementSibling;
+ return slide ? slide : lastSlide();
+ };
+
+ if(detail && detail.action) {
+
+ const { action, target } = detail;
+
+ let slide;
+ switch (action.toLowerCase()) {
+ case 'select':
+ slide = getSlide(target);
+ this.dispatchSelectEvent_(slide);
+ break;
+ case 'first':
+ slide = firstSlide();
+ break;
+ case 'next':
+ slide = nextSlide();
+ break;
+ case 'prev':
+ slide = prevSlide();
+ break;
+ case 'last':
+ slide = lastSlide();
+ break;
+ case 'upgrade':
+ this.upgradeSlides();
+ break;
+ default:
+ throw new Error(`Unknown action "${action}". Action must be one of "first", "next", "prev", "last", "select" or "upgrade"`);
+ }
+
+ if (slide) {
+ const a = slide.querySelector('a');
+ if (a) {
+ a.focus();
+ }
+ else {
+ slide.focus();
+ }
+
+ // Workaround for JSDom testing:
+ // In JsDom 'element.focus()' does not trigger any focus event
+ if(!slide.hasAttribute('aria-selected')) {
+ this.selectSlide_(slide);
+ }
+
+ }
+ }
+ };
+ MaterialExtLightboard.prototype['command'] = MaterialExtLightboard.prototype.command;
+
+
+ /**
+ * Initialize component
+ */
+ MaterialExtLightboard.prototype.init = function() {
+
+ const keydownHandler = event => {
+
+ if(event.target !== this.element_) {
+ let action;
+ let target;
+ switch (event.keyCode) {
+ case VK_HOME:
+ action = 'first';
+ break;
+ case VK_END:
+ action = 'last';
+ break;
+ case VK_ARROW_UP:
+ case VK_ARROW_LEFT:
+ action = 'prev';
+ break;
+ case VK_ARROW_DOWN:
+ case VK_ARROW_RIGHT:
+ action = 'next';
+ break;
+ case VK_ENTER:
+ case VK_SPACE:
+ action = 'select';
+ target = event.target;
+ break;
+ }
+ if(action) {
+ event.preventDefault();
+ event.stopPropagation();
+ this.command( { action: action, target: target } );
+ }
+ }
+ };
+
+ const clickHandler = event => {
+ event.preventDefault();
+ event.stopPropagation();
+
+ if(event.target !== this.element_) {
+ this.command( { action: 'select', target: event.target } );
+ }
+ };
+
+ const focusHandler = event => {
+ event.preventDefault();
+ event.stopPropagation();
+
+ if(event.target !== this.element_) {
+ this.selectSlide_(event.target);
+ }
+ };
+
+
+ if (this.element_) {
+ this.element_.setAttribute('role', LIGHTBOARD_ROLE);
+
+ if (this.element_.classList.contains(MDL_RIPPLE_EFFECT)) {
+ this.element_.classList.add(MDL_RIPPLE_EFFECT_IGNORE_EVENTS);
+ }
+
+ // Remove listeners, just in case ...
+ this.element_.removeEventListener('command', this.commandHandler_);
+ this.element_.removeEventListener('keydown', keydownHandler);
+ this.element_.removeEventListener('click', clickHandler);
+ this.element_.removeEventListener('focus', focusHandler);
+
+ this.element_.addEventListener('command', this.commandHandler_.bind(this), false);
+ this.element_.addEventListener('keydown', keydownHandler, true);
+ this.element_.addEventListener('click', clickHandler, true);
+ this.element_.addEventListener('focus', focusHandler, true);
+
+ this.upgradeSlides();
+
+ this.element_.classList.add(IS_UPGRADED);
+ }
+ };
+
+ // The component registers itself. It can assume componentHandler is available
+ // in the global scope.
+ /* eslint no-undef: 0 */
+ /* jshint undef:false */
+ componentHandler.register({
+ constructor: MaterialExtLightboard,
+ classAsString: 'MaterialExtLightboard',
+ cssClass: 'mdlext-js-lightboard',
+ widget: true
+ });
+
+})();
diff --git a/node_modules/mdl-ext/src/lightboard/readme.md b/node_modules/mdl-ext/src/lightboard/readme.md
new file mode 100644
index 0000000..429e88e
--- /dev/null
+++ b/node_modules/mdl-ext/src/lightboard/readme.md
@@ -0,0 +1,447 @@
+# Lightboard
+
+![Lightboard](../../etc/lightboard.png)
+
+Thumbnails in a responsive, fluent grid.
+
+## Introduction
+A lightboard is a translucent surface illuminated from behind, used for situations where a shape laid
+upon the surface needs to be seen with high contrast. In the "old days" of photography photograpers
+used a lightboard to get a quick view of, sorting and organizing their slides.
+
+The Material Design Lite Ext (MDLEXT) lightboard is defined and enclosed by a container element. The slides are
+distributed in a row column fashion, with repect to the available screen size. The slides scales proportionally to fill
+available horizontal space, or the available content size, depending on the type of queries you choose to apply
+for your responsive breakpoints. The number of slides per row depends on available space. The component
+adds `role='grid'` to the lightboard and `role='gridcell` to the individual slides.
+
+The Material Design Lite Ext (MDLEXT) lightboard has two versions; one version based on media queries and one version
+based on **element queries**.
+
+### How to use the eq.js version of MDLEXT lightboard
+
+ 1. Install [eq.js](https://github.com/Snugug/eq.js).
+```sh
+$ npm install --save eq.js
+```
+
+ 2. Import `mdl-ext-eqjs.scss` in your main SASS file. Remove `mdl-ext.scss` - they can not co exist.
+```css
+@import '../node_modules/mdl-ext/src/mdl-ext-eqjs';
+```
+
+ 3. Import or Require `eq.js`.
+```javascript
+const eqjs = require('eq.js'); // ... or: import eqjs from 'eq.js';
+```
+
+ 4. Upgrade DOM and trigger `eq.js`<br/>
+If you're loading html fragments, using e.g. Ajax, then upgrade DOM and trigger `eq.js` after page load.
+
+```javascript
+window.fetch(href, {method: 'get'})
+ .then(response => response.text())
+ .then(text => {
+ contentPanelEl.insertAdjacentHTML('afterbegin', text);
+
+ // Upgrade DOM
+ componentHandler.upgradeDom();
+
+ // Trigger eq.js
+ eqjs.refreshNodes();
+ eqjs.query(undefined, true);
+})
+.catch(err => console.error(err));
+```
+
+An example of how to use `eq.js` in a SPA can be found [here](https://github.com/leifoolsen/mdl-webpack).
+
+## To include a MDLEXT lightboard component
+ 1. Code a `<ul>` element with `class="mdlext-lightboard mdlext-js-lightboard"` to hold the lightboard slides.
+```html
+<ul class="mdlext-lightboard mdlext-js-lightboard">
+</ul>
+```
+
+ 2. Code a `<li>` element with `class="mdlext-lightboard__slide"` to hold an individual slide.
+```html
+<ul class="mdlext-lightboard mdlext-js-lightboard">
+ <li class="mdlext-lightboard__slide">
+ <li>
+</ul>
+```
+
+ 3. Code an `<a href="#">` element with `class="mdlext-lightboard__slide__frame"` to hold the slide frame. Optionally add a href to a large version of the image shown in the slide.
+```html
+<ul class="mdlext-lightboard mdlext-js-lightboard">
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ </a>
+ <li>
+</ul>
+```
+
+ 4. Code a `<figure>` element (decorates frame and center image in slide).
+```html
+<ul class="mdlext-lightboard mdlext-js-lightboard">
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ </figure>
+ </a>
+ <li>
+</ul>
+```
+
+ 5. Inside the `<figure>` element add an `<img>` element with reference to the thumbnail image to be shown in slide. Optionally add a `<figcaption>` element to hold the image title.
+```html
+<ul class="mdlext-lightboard mdlext-js-lightboard">
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="_D802591.jpg" title="Whooper swans in flight"/>
+ <figcaption>_D802591.jpg</figcaption>
+ </figure>
+ </a>
+ <li>
+</ul>
+```
+
+ 6. Repeat steps 2..5 for each slide required.
+
+### Example
+Lightboard with eight slides, ripple effect on each slide, no spacing between slides, subscribes to lightboard `select` event.
+
+```html
+<ul id="lightboard-1" class="mdlext-lightboard mdlext-js-lightboard
+ mdlext-lightboard--no-spacing
+ mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events">
+
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="_D802141.jpg" title="Northern goshawk with prey"/>
+ <figcaption>_D802141.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="_D802591.jpg" title="Whooper swans in flight"/>
+ <figcaption>_D802591.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="_D804370-3.jpg" title="European green woodpecker"/>
+ <figcaption>_D804370-3.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="_D808689.jpg" title="The bridge"/>
+ <figcaption>_D808689.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="_D802181.jpg" title="Landscape in blue pastel"/>
+ <figcaption>_D802181.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="_D800912.jpg" title="Hiking the mountains of Dovre"/>
+ <figcaption>_D800912.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="_D809453-_D809457-4.jpg" title="Train to nowhwere. Ny Aalesund, Spitsbergen." />
+ <figcaption>_D809453-_D809457-4.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="_DSC8214.jpg" title="Blues"/>
+ <figcaption>_DSC8214.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+</ul>
+
+<script>
+ window.addEventListener('load', function() {
+ var lightboard = document.querySelector('#lightboard-1');
+ lightboard.addEventListener('select', function(e) {
+ console.log('Slide selected. Source:', e.detail.source);
+ });
+ });
+</script>
+```
+
+## Keyboard interaction
+The lightboard interacts with the following keyboard keys.
+
+* `Tab` - When focus is on a slide, pressing the `Tab` key moves focus in the following manner:
+ 1. If interactive glyphs or menus are present in the slide frame, focus moves to each in order. (Not implemented yet)
+ 2. The next `Tab` key press moves focus as follows:
+ * If there is a next slide, focus moves to the next slide.
+ * If focus is on the last slide, focus moves to the first focusable element outside the lightboard component.
+* `Left arrow` - Moves focus to the previous slide. If the current slide is the first slide, focus moves to the last slide.
+* `Right arrow` - Moves focus to the next slide. If the current slide is the last slide, focus moves to the first slide.
+* `Up arrow` - behaves the same as left arrow.
+* `Down arrow` - behaves the same as right arrow.
+* `End` - When focus is on a slide, an `End` key press moves focus to the last slide.
+* `Home` - When focus is on a slide, a `Home` key press moves focus to the first slide.
+* `Enter/Space` - When focus is on slide, pressing `Enter`/`Space` selects that particular slide. The lightboard emits a **select** event.
+* `Shift+Tab` - Generally the reverse of `Tab`.
+
+
+## Events
+Interaction with the component programmatically is performed receiving events from the component or by sending events to
+the component (or by using the public api).
+
+### Events the component listenes to
+A client can send a `command` custom event to the lightboard. The command event holds a detail object defining the action
+to perform and a optionally a target for the action.
+
+The detail object has the following structure:
+
+```javascript
+detail: {
+ action, // "first", "last", "next", "prev", "upgrade" or "select"
+ target // Target, the slide that should be affected by the event
+}
+```
+
+Possible actions are:
+
+#### first
+Focuses the first slide.
+
+```javascript
+myLightboard = document.querySelector('#my-lightboard');
+ce = new CustomEvent('command', { detail: { action : 'first' } });
+myLightboard.dispatchEvent(ce);
+```
+
+#### last
+Focuses the last slide.
+
+```javascript
+myLightboard = document.querySelector('#my-lightboard');
+ce = new CustomEvent('command', { detail: { action : 'last' } });
+myLightboard.dispatchEvent(ce);
+```
+
+#### next
+Focuses the next slide.
+
+```javascript
+myLightboard = document.querySelector('#my-lightboard');
+ce = new CustomEvent('command', { detail: { action : 'next' } });
+myLightboard.dispatchEvent(ce);
+```
+
+#### prev
+Focuses the previous slide.
+
+```javascript
+myLightboard = document.querySelector('#my-lightboard');
+ce = new CustomEvent('command', { detail: { action : 'prev' } });
+myLightboard.dispatchEvent(ce);
+```
+
+#### select
+Selects a slide, i.e. adds `aria-selected="true"` on the targeted slide. The lightboard responds with a `select` event.
+
+```javascript
+myLightboard = document.querySelector('#my-lightboard');
+slide = lightboard.querySelector('.mdlext-lightboard__slide:nth-child(2)');
+ce = new CustomEvent('command', { detail: { action : 'prev', target: slide } });
+myLightboard.dispatchEvent(ce);
+```
+
+#### upgrade
+Upgrade slides. If you add slides to the lightboard after the page has loaded, you must call `upgrade` to
+notify the lightboard component about the new slides.
+
+```javascript
+myLightboard = document.querySelector('#my-lightboard');
+slide =
+ '<li class="mdlext-lightboard__slide">'
+ +' <a href="#" class="mdlext-lightboard__slide__frame">'
+ +' <figure>'
+ +' <img src="_D802181.jpg" title="Landscape in blue pastel"/>'
+ +' <figcaption>_D802181.jpg</figcaption>'
+ +' </figure>'
+ +' </a>'
+ +'</li>';
+
+myLightboard.insertAdjacentHTML('beforeend', slide);
+ce = new CustomEvent('command', { detail: { action : 'upgrade' } });
+myLightboard.dispatchEvent(ce);
+```
+
+### Events emitted from the component
+The lightboard emits a custom `select` event when a slide is clicked. The event has a detail object with the following content:
+```
+{
+ source // the slide instance that caused the event
+}
+```
+
+Set up an event listener to receive the select event.
+```javascript
+document.querySelector('#my-lightboard').addEventListener('select', function(e) {
+ console.log('Slide selected:', e.detail.source);
+});
+```
+
+Trigger the event.
+```javascript
+myLightboard = document.querySelector('#my-lightboard');
+slide = lightboard.querySelector('.mdlext-lightboard__slide:nth-child(2)');
+ce = new CustomEvent('command', { detail: { action : 'select', target: slide } });
+myLightboard.dispatchEvent(ce);
+```
+
+## Public methods
+
+### upgradeSlides()
+Upgrade slides. If you add slides to the lightboard after the page has loaded, you must call `upgradeSlides` to
+notify the component about the new slides.
+
+```javascript
+slide =
+ '<li class="mdlext-lightboard__slide">'
+ +' <a href="#" class="mdlext-lightboard__slide__frame">'
+ +' <figure>'
+ +' <img src="_D802181.jpg" title="Landscape in blue pastel"/>'
+ +' <figcaption>_D802181.jpg</figcaption>'
+ +' </figure>'
+ +' </a>'
+ +'</li>';
+
+myLightboard = document.querySelector('#my-lightboard');
+myLightboard.insertAdjacentHTML('beforeend', slide);
+myLightboard.MaterialExtLightboard.upgradeSlides();
+```
+
+### command( detail )
+Executes an action, optionally targeting a specific slide. The actions corresponds to the custom events defined for this
+component.
+
+The detail object parameter has the following structure:
+```javascript
+detail: {
+ action, // "first", "last", "next", "prev", "upgrade" or "select"
+ target // Target, the slide that should be affected by the event
+}
+```
+
+Possible actions are:
+
+#### first: command( {action: 'first' } )
+Focuses the first slide.
+
+```javascript
+myLightboard = document.querySelector('#my-lightboard');
+myLightboard.MaterialExtLightboard.command( {action: 'first'} );
+```
+
+#### last: command( {action: 'last' } )
+Focuses the last slide.
+
+```javascript
+myLightboard = document.querySelector('#my-lightboard');
+myLightboard.MaterialExtLightboard.command( {action: 'last'} );
+```
+
+#### next: command( {action: 'next' } )
+Focuses the next slide.
+
+```javascript
+myLightboard = document.querySelector('#my-lightboard');
+myLightboard.MaterialExtLightboard.command( {action: 'next'} );
+```
+
+#### prev: command( {action: 'prev' } )
+Focuses the previous slide.
+
+```javascript
+myLightboard = document.querySelector('#my-lightboard');
+myLightboard.MaterialExtLightboard.command( {action: 'prev'} );
+```
+
+#### select: command( {action: 'first', target: slide } )
+Selects a slide, i.e. adds `aria-selected="true"` on the targeted slide. The lightboard responds with a `select` event.
+
+```javascript
+myLightboard = document.querySelector('#my-lightboard');
+slide = lightboard.querySelector('.mdlext-lightboard__slide:nth-child(2)');
+myLightboard.MaterialExtLightboard.command( {action: 'prev', target: slide} );
+```
+
+#### upgrade: command( {action: 'upgrade' } )
+Upgrade slides. If you add slides to the lightboard after the page has loaded, you must call `upgrade` to
+notify the lightboard component about the new slides.
+
+```javascript
+myLightboard = document.querySelector('#my-lightboard');
+slide =
+ '<li class="mdlext-lightboard__slide">'
+ +' <a href="#" class="mdlext-lightboard__slide__frame">'
+ +' <figure>'
+ +' <img src="_D802181.jpg" title="Landscape in blue pastel"/>'
+ +' <figcaption>_D802181.jpg</figcaption>'
+ +' </figure>'
+ +' </a>'
+ +'</li>';
+
+myLightboard.insertAdjacentHTML('beforeend', slide);
+myLightboard.MaterialExtLightboard.command( {action: 'upgrade'} );
+```
+
+## Configuration options
+
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements to the lightboard.
+The table below lists the available classes and their effects.
+
+| MDLEXT class | Effect | Remarks |
+|--------------|--------|---------|
+| `mdlext-lightboard` | Defines a container as an MDLEXT lightboard component | Required on `<ul>` element |
+| `mdlext-js-lightboard` | Assigns basic MDL behavior to lightboard | Required on `<ul>` element |
+| `mdlext-lightboard--no-spacing` | Modifies the slides to have no margin between them. | Optional on `<ul>` element |
+| `mdlext-lightboard__slide` | Defines a slide | Required on `<li>` element |
+| `mdlext-lightboard__slide__frame` | Defines the slide frame, makes the frame focusable and selectable | Required on `<a>` element. First inner element of `<li>` |
+| `mdl-js-ripple-effect` | Applies ripple click effect to slides | Optional; goes on "outer" `<ul>` element |
+| `mdl-js-ripple-effect--ignore-events` | | Should be added when the component initializes, but that does not seem to happen due to bug/limitation in MDL. For now, add this class if `mdl-js-ripple-effect` class is applied |
+
+
+A lightboard and its assosiated slides has the following roles.
+
+| Attribute | Effect | Remarks |
+|-----------|--------|---------|
+| `role="grid"` | Defines the lightboard as a WAI-ARIA grid | Added to `mdlext-lightboard` when component innitializes |
+| `role="gridcell"` | Defines the slide as a WAI-ARIA cell | Added to `mdlext-lightboard__slide` when component innitializes |
+| `aria-selected` | Defines a slide as selected | Added to `mdlext-lightboard__slide` when a slide is clicked |
+
+
+## How to use the component programmatically
+Refer to [snippets/lightboard.html](./snippets/lightboard.html) or the [tests](../../test/lightboard/lightboard.spec.js)
+for detailed usage.
diff --git a/node_modules/mdl-ext/src/lightboard/snippets/lightboard.html b/node_modules/mdl-ext/src/lightboard/snippets/lightboard.html
new file mode 100644
index 0000000..555a4d8
--- /dev/null
+++ b/node_modules/mdl-ext/src/lightboard/snippets/lightboard.html
@@ -0,0 +1,174 @@
+<p style="margin-bottom:32px;">A lightboard is a translucent surface illuminated from behind, used for
+ situations where a shape laid upon the surface needs to be seen with high contrast. In the "old days"
+ of photography photograpers used a lightboard to get a quick view of, sorting and organizing their slides.
+</p>
+
+<ul id="lightboard-1" class="mdlext-lightboard mdlext-js-lightboard mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events">
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D802141.jpg" title="Northern goshawk with prey"/>
+ <figcaption>_D802141.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D802591.jpg" title="Whooper swans in flight"/>
+ <figcaption>_D802591.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D804370-3.jpg" title="European green woodpecker"/>
+ <figcaption>_D804370-3.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D808689.jpg" title="The bridge"/>
+ <figcaption>_D808689.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D802181.jpg" title="Landscape in blue pastel"/>
+ <figcaption>_D802181.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800912.jpg" title="Hiking the mountains of Dovre"/>
+ <figcaption>_D800912.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D809453-_D809457-4.jpg" title="Train to nowhwere. Ny Aalesund, Spitsbergen." />
+ <figcaption>_D809453-_D809457-4.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_DSC8214.jpg" title="Blues"/>
+ <figcaption>_DSC8214.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800017.jpg" />
+ <figcaption>_D800017.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800023.jpg" />
+ <figcaption>_D800023.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800851.jpg" />
+ <figcaption>_D800851.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800166.jpg" />
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800951.jpg" />
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D801188.jpg" />
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D801205-2.jpg" />
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D801274.jpg" />
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D801392.jpg" />
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D801952-4.jpg" />
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D807603.jpg" />
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide">
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D807689.jpg" />
+ </figure>
+ </a>
+ </li>
+</ul>
+
+<p class="mdl-typography--caption" style="margin-top: 32px;">
+ All images appearing in this page are the exclusive property of Leif Olsen and are protected under the United States and International Copyright laws.
+ The images may not be reproduced or manipulated without the written permission of Leif Olsen.
+ Use of any image as the basis for another photographic concept or illustration (digital, artist rendering or alike) is a violation of the United States and International Copyright laws.
+ All images are copyrighted © Leif Olsen, 2016.
+</p>
+
+<script>
+ window.addEventListener('load', function() {
+ var lightboard = document.querySelector('#lightboard-1');
+ lightboard.addEventListener('select', function(e) {
+ console.log('Slide selected. Source:', e.detail.source);
+ });
+ });
+</script>
diff --git a/node_modules/mdl-ext/src/lightbox/_lightbox.scss b/node_modules/mdl-ext/src/lightbox/_lightbox.scss
new file mode 100644
index 0000000..721d181
--- /dev/null
+++ b/node_modules/mdl-ext/src/lightbox/_lightbox.scss
@@ -0,0 +1,141 @@
+@charset "UTF-8";
+
+/**
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Use of this module requires the user to include variables from material-design-lite
+//@import "../../node_modules/material-design-lite/src/variables";
+//@import "../../node_modules/material-design-lite/src/mixins";
+@import "../variables";
+
+.mdlext-lightbox {
+ user-select: none;
+ cursor: default;
+ position: relative;
+ width: auto;
+ max-width: 100%;
+ margin: 0 auto;
+ border: $mdlext-lightbox-border;
+ border-radius: $mdlext-lightbox-border-radius;
+ background-color: $mdlext-lightbox-background-color;
+ box-sizing: border-box;
+ outline: 0;
+ display: block; // display: flex and IE11 has issues with reposition. Set display:block for now.
+
+ *,
+ *::before,
+ *::after,
+ input[type="search"] {
+ box-sizing: border-box;
+ }
+
+ .mdlext-lightbox__slider {
+ // Displays prevvious, current and next image while dragging
+ // Elements are created by lightbox component when dragging starts
+ position: absolute;
+ top: 0;
+ left: 0;
+ display: flex;
+ justify-content: center;
+
+ .mdlext-lightbox__slider__slide {
+ flex-shrink: 0;
+ display: block;
+ text-align: left;
+ color: #7f7f7f;
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+
+ //&:nth-child(1),
+ //&:nth-child(3) {
+ // filter: blur(1px);
+ //}
+ }
+ }
+
+ figure {
+ margin: $mdlext-lightbox-figure-margin;
+ padding: $mdlext-lightbox-figure-padding;
+ position: relative;
+
+ img {
+ width: 100%;
+ max-width: 100%;
+ height: auto;
+ border: 0;
+ outline: 0;
+ }
+ figcaption {
+ @include typo-caption($colorContrast: false, $usePreferred: true);
+
+ display: block;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ max-width: 100%;
+ height: auto;
+ max-height: 50%;
+ overflow: auto;
+ padding: 8px;
+ background-color: $mdlext-lightbox-figcaption-background-color;
+ transform-origin: bottom;
+ transform: scaleY(0);
+ transition: 0.2s ease-in-out;
+
+ &.mdlext-lightbox__show-figcaption {
+ transform: scaleY(1);
+ }
+ tbody {
+ th {
+ text-align: left;
+ }
+ th,
+ td {
+ vertical-align: text-top;
+ }
+ }
+ }
+ }
+ .mdl-card__menu {
+ color: #ffffff;
+ z-index: 1;
+ }
+ footer {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ background-color: $mdlext-lightbox-footer-background-color;
+
+ .mdl-card__supporting-text {
+ flex: 1;
+ overflow: hidden;
+ padding: 0;
+ height: $card-supporting-text-line-height;
+ width: 100%;
+ }
+ nav {
+ display: flex;
+ }
+ }
+
+ &.mdlext-lightbox--sticky-footer footer {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ }
+}
diff --git a/node_modules/mdl-ext/src/lightbox/lightbox.js b/node_modules/mdl-ext/src/lightbox/lightbox.js
new file mode 100644
index 0000000..2e14463
--- /dev/null
+++ b/node_modules/mdl-ext/src/lightbox/lightbox.js
@@ -0,0 +1,359 @@
+/**
+ * @license
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+
+/**
+ * Responsive Lightbox
+ */
+
+import fullThrottle from '../utils/full-throttle';
+import {
+ VK_ESC,
+ VK_SPACE,
+ VK_END,
+ VK_HOME,
+ VK_ARROW_LEFT,
+ VK_ARROW_UP,
+ VK_ARROW_RIGHT,
+ VK_ARROW_DOWN,
+ IS_UPGRADED
+} from '../utils/constants';
+
+(function() {
+ 'use strict';
+
+ const LIGHTBOX = 'mdlext-lightbox';
+ const LIGHTBOX_SLIDER = 'mdlext-lightbox__slider';
+ const LIGHTBOX_SLIDER_SLIDE = 'mdlext-lightbox__slider__slide';
+ const STICKY_FOOTER = 'mdlext-lightbox--sticky-footer';
+ const BUTTON = 'mdl-button';
+
+ /**
+ * https://github.com/google/material-design-lite/issues/4205
+ * @constructor
+ * @param {Element} element The element that will be upgraded.
+ */
+ const MaterialExtLightbox = function MaterialExtLightbox(element) {
+ // Stores the element.
+ this.element_ = element;
+
+ // Initialize instance.
+ this.init();
+ };
+ window['MaterialExtLightbox'] = MaterialExtLightbox;
+
+
+ /**
+ * Handle keypress
+ * @param event
+ * @private
+ */
+ MaterialExtLightbox.prototype.keyDownHandler_ = function(event) {
+
+ if (event) {
+ if ( event.keyCode === VK_ESC || event.keyCode === VK_SPACE
+ || event.keyCode === VK_END || event.keyCode === VK_HOME
+ || event.keyCode === VK_ARROW_UP || event.keyCode === VK_ARROW_LEFT
+ || event.keyCode === VK_ARROW_DOWN || event.keyCode === VK_ARROW_RIGHT) {
+
+ if(event.keyCode !== VK_ESC) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+
+ let action = 'first';
+ if (event.keyCode === VK_END) {
+ action = 'last';
+ }
+ else if (event.keyCode === VK_ARROW_UP || event.keyCode === VK_ARROW_LEFT) {
+ action = 'prev';
+ }
+ else if (event.keyCode === VK_ARROW_DOWN || event.keyCode === VK_ARROW_RIGHT) {
+ action = 'next';
+ }
+ else if (event.keyCode === VK_SPACE) {
+ action = 'select';
+ }
+ else if (event.keyCode === VK_ESC) {
+ action = 'cancel';
+ }
+
+ dispatchAction_(action, this);
+ }
+ }
+ };
+
+ /**
+ * Handle button clicks
+ * @param event
+ * @private
+ */
+ MaterialExtLightbox.prototype.buttonClickHandler_ = function(event) {
+
+ if (event) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ dispatchAction_(this.getAttribute('data-action') || '', this);
+
+ const n = this.closest(`.${LIGHTBOX}`);
+ if(n) {
+ n.focus();
+ }
+ }
+ };
+
+ /**
+ * Dispatches an action custom event
+ * @param action
+ * @param source
+ * @param target
+ * @private
+ */
+ const dispatchAction_ = (action, source, target = source) => {
+
+ target.dispatchEvent(new CustomEvent('action', {
+ bubbles: true,
+ cancelable: true,
+ detail: {
+ action: action || '',
+ source: source
+ }
+ }));
+ };
+
+ /**
+ * Reposition dialog if component parent element is "DIALOG"
+ * @param lightboxElement
+ * @private
+ */
+ const repositionDialog_ = lightboxElement => {
+ const footerHeight = (footer, isSticky) => isSticky && footer ? footer.offsetHeight : 0;
+
+ const reposition = (dialog, fh) => {
+ if (window.getComputedStyle(dialog).position === 'absolute') {
+ const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
+ const topValue = scrollTop + (window.innerHeight - dialog.offsetHeight - fh) / 2;
+ dialog.style.top = `${Math.max(scrollTop, topValue)}px`;
+ }
+ };
+
+ const p = lightboxElement.parentNode;
+ const dialog = p && p.nodeName === 'DIALOG' ? p : null;
+
+ if(dialog && dialog.hasAttribute('open')) {
+ lightboxElement.style.width = 'auto';
+ lightboxElement.style.maxWidth = '100%';
+ const img = lightboxElement.querySelector('img');
+ if(img) {
+ lightboxElement.style.maxWidth = img.naturalWidth !== undefined ? `${img.naturalWidth}px` : `${img.width}px` || '100%';
+ }
+
+ const fh = footerHeight(lightboxElement.querySelector('footer'), lightboxElement.classList.contains(STICKY_FOOTER));
+ const vh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0) - fh;
+ if (dialog.offsetHeight > vh) {
+ let n = 0;
+ while(dialog.offsetHeight > vh && ++n < 4) {
+ lightboxElement.style.width = `${lightboxElement.offsetWidth * vh / lightboxElement.offsetHeight}px`;
+ }
+ }
+ reposition(dialog, fh);
+ }
+ };
+
+ /**
+ * Handle image load
+ * @param event
+ * @private
+ */
+
+ MaterialExtLightbox.prototype.imgLoadHandler_ = function( /*event*/ ) {
+ repositionDialog_(this);
+ };
+
+
+ /**
+ * Handle image drag
+ * @param event
+ * @private
+ */
+ MaterialExtLightbox.prototype.imgDragHandler_ = function(event ) {
+
+ const setStyles = ( element, properties ) => {
+ //noinspection JSAnnotator
+ for(const [key, value] of Object.entries(properties)) {
+ element.style[key] = value;
+ }
+ // ... or:
+ //for (const key in properties) {
+ // element.style[key] = properties[key];
+ //}
+ };
+
+ event.preventDefault();
+ //event.stopPropagation();
+
+ const x = event.clientX || (event.touches !== undefined ? event.touches[0].clientX : 0);
+
+ const img = this;
+ img.style.opacity = '0.2';
+
+ const slider = document.createElement('div');
+ slider.classList.add(LIGHTBOX_SLIDER);
+ setStyles(slider, {'width': `${img.offsetWidth}px`, 'height': `${img.offsetHeight}px`} );
+
+ let slide = document.createElement('div');
+ slide.classList.add(LIGHTBOX_SLIDER_SLIDE);
+ slide.textContent = '>';
+ setStyles(slide, {
+ 'width' : `${img.offsetWidth}px`,
+ 'height' : `${img.offsetHeight}px`,
+ 'line-height' : `${img.offsetHeight}px`,
+ 'font-size' : `${img.offsetHeight/4}px`,
+ 'text-align' : 'right',
+ 'background-image': `url("${img.getAttribute('data-img-url-prev') || ''}")`
+ });
+ slider.appendChild(slide);
+
+ slide = document.createElement('div');
+ slide.classList.add(LIGHTBOX_SLIDER_SLIDE);
+ setStyles(slide, {
+ 'width' : `${img.offsetWidth}px`,
+ 'height' : `${img.offsetHeight}px`,
+ 'background-image': `url("${img.src}")`
+ });
+ slider.appendChild(slide);
+
+ slide = document.createElement('div');
+ slide.classList.add(LIGHTBOX_SLIDER_SLIDE);
+ slide.textContent = '<';
+ setStyles(slide, {
+ 'width' : `${img.offsetWidth}px`,
+ 'height' : `${img.offsetHeight}px`,
+ 'line-height' : `${img.offsetHeight}px`,
+ 'font-size' : `${img.offsetHeight/4}px`,
+ 'text-align' : 'left',
+ 'background-image': `url("${img.getAttribute('data-img-url-next') || ''}")`
+ });
+ slider.appendChild(slide);
+
+ img.parentNode.appendChild(slider);
+
+
+ // drag handler
+ const drag = e => {
+ e.preventDefault();
+ const dx = (e.clientX || (e.touches !== undefined ? e.touches[0].clientX : 0)) - x; // TODO: maybe rewrite to improve performance
+
+ if(slider.offsetWidth - Math.abs(dx) > 19) {
+ slider.style.left = `${dx}px`;
+ }
+ };
+
+ // end drag handler
+ const endDrag = e => {
+ e.preventDefault();
+ //e.stopPropagation();
+
+ window.removeEventListener('mousemove', drag);
+ window.removeEventListener('touchmove', drag);
+ window.removeEventListener('mouseup', endDrag);
+ window.removeEventListener('touchend', endDrag);
+
+ const dx = slider.offsetLeft;
+ img.parentNode.removeChild(slider);
+ img.style.opacity = '1.0';
+
+ if(Math.abs(dx) > 19) {
+ dispatchAction_( (dx > 0 ? 'prev' : 'next') , img);
+ }
+ };
+
+ window.addEventListener('mousemove', drag);
+ window.addEventListener('touchmove', drag);
+ window.addEventListener('mouseup', endDrag);
+ window.addEventListener('touchend',endDrag);
+ };
+
+
+ /**
+ * Initialize component
+ */
+ MaterialExtLightbox.prototype.init = function() {
+
+ if (this.element_) {
+ // Do the init required for this component to work
+ this.element_.addEventListener('keydown', this.keyDownHandler_.bind(this.element_), true);
+
+ if(!Number.isInteger(this.element_.getAttribute('tabindex'))) {
+ this.element_.setAttribute('tabindex', 1);
+ }
+
+ [...this.element_.querySelectorAll(`.${BUTTON}`)].forEach( button =>
+ button.addEventListener('click', this.buttonClickHandler_.bind(button), false)
+ );
+
+ const figcaption = this.element_.querySelector('figcaption');
+ if(figcaption) {
+ figcaption.addEventListener('click', this.buttonClickHandler_.bind(figcaption), false);
+ }
+
+ const footer = this.element_.querySelector('footer');
+ if(footer) {
+ footer.addEventListener('click', this.buttonClickHandler_.bind(footer), false);
+ }
+
+ const img = this.element_.querySelector('img');
+ if(img) {
+ img.addEventListener('load', this.imgLoadHandler_.bind(this.element_), false);
+ img.addEventListener('click', e => e.preventDefault(), true);
+ img.addEventListener('mousedown', this.imgDragHandler_.bind(img), true);
+ img.addEventListener('touchstart', this.imgDragHandler_.bind(img), true);
+ }
+ window.addEventListener('resize', fullThrottle( () => repositionDialog_(this.element_) ));
+ window.addEventListener('orientationchange', () => repositionDialog_(this.element_));
+
+ // Set upgraded flag
+ this.element_.classList.add(IS_UPGRADED);
+ }
+ };
+
+ /*
+ * Downgrade component
+ * E.g remove listeners and clean up resources
+ *
+ * Nothing to downgrade
+ *
+ MaterialExtLightbox.prototype.mdlDowngrade_ = function() {
+ };
+ */
+
+ /**
+ * The component registers itself. It can assume componentHandler is available in the global scope.
+ */
+ /* jshint undef:false */
+ componentHandler.register({
+ constructor: MaterialExtLightbox,
+ classAsString: 'MaterialExtLightbox',
+ cssClass: 'mdlext-js-lightbox'
+ });
+
+})();
+
diff --git a/node_modules/mdl-ext/src/lightbox/readme.md b/node_modules/mdl-ext/src/lightbox/readme.md
new file mode 100644
index 0000000..5744920
--- /dev/null
+++ b/node_modules/mdl-ext/src/lightbox/readme.md
@@ -0,0 +1,322 @@
+# Lightbox
+
+![Lightbox](../../etc/lightbox.png)
+A responsive lightbox to be used in conjunction with e.g. a MDLEXT lightboard component.
+
+## Introduction
+The Material Design Lite Ext (MDLEXT) Lightbox displays an image filling the screen, and dimming out the rest of the web page.
+It acts as a modal dialog, using the `<dialog>` element as a container for the lightbox. The component uses
+the [Material Design Lite Card component](http://www.getmdl.io/components/index.html#cards-section) to provide a layout for the lightbox.
+
+## How to use the Google Chrome Dialog polyfill
+
+ 1. Install [Google Chrome Dialog polyfill](https://github.com/GoogleChrome/dialog-polyfill).
+```sh
+$ npm install --save dialog-polyfill
+```
+
+ 2. Use the polyfill in a static page.
+```html
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Material Design Lite Extensions</title>
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&lang=en">
+ <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
+ <link rel="stylesheet" href="node_modules/dialog-polyfill/dialog-polyfill.css" />
+ <link rel="stylesheet" href="node_modules/material-design-lite/material.css" />
+ <link rel="stylesheet" href="node_modules/mdl-ext/lib/mdl-ext.min.css" />
+</head>
+<body>
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer">
+ <main class="mdl-layout__content">
+ </main
+</div>
+<script type="text/javascript" src="node_modules/dialog-polyfill/dialog-polyfill.js" charset="utf-8"></script>
+<script type="text/javascript" src="node_modules/material-design-lite/material.min.js" charset="utf-8"></script>
+<script type="text/javascript" src="node_modules/mdl-ext/lib/mdl-ext.min.js" charset="utf-8"></script>
+</body>
+</html>
+```
+
+ 3. Use it in your (Webpack) build.
+
+ 3.1. Import `dialog-polyfill.css` in your main SASS file..
+```css
+@import '../node_modules/dialog-polyfill/dialog-polyfill.css';
+```
+
+ 3.2. Require `dialog-polyfill`.
+```javascript
+const dialogPolyfill = require('dialog-polyfill/dialog-polyfill');
+```
+
+ ... or import the `dialog-polyfill`.
+```javascript
+import { dialogPolyfill } from 'dialog-polyfill/dialog-polyfill';
+```
+
+>Adjust path to `node_modules` (libraries) according to where your files are located.
+>For more information about the dialog polyfill, refer to the [Google Chrome Dialog polyfill](https://github.com/GoogleChrome/dialog-polyfill) documentaion and the Material Design Lite [Dialog](http://www.getmdl.io/components/index.html#dialog-section) section.
+
+## To include a MDLEXT lightbox component
+ 1. Code a `<dialog>` element with `class="mdlext-dialog"` to display the lightbox as a modal dialog.
+```html
+<dialog class="mdlext-dialog">
+</dialog>
+```
+
+ 2. Code a `<div>` element with `class="mdlext-lightbox mdlext-js-lightbox mdl-card"` to hold the lightbox.
+```html
+<dialog class="mdlext-dialog">
+ <div class="mdlext-lightbox mdlext-js-lightbox mdl-card">
+ </div>
+</dialog>
+```
+
+ 3. Code a `<div>` element with `class="mdl-card__menu mdl-color-text--white mdl-typography--body-2-color-contrast"` to hold the close dialog button.
+```html
+<dialog class="mdlext-dialog">
+ <div class="mdlext-lightbox mdlext-js-lightbox mdl-card">
+ <div class="mdl-card__menu mdl-color-text--white mdl-typography--body-2-color-contrast">
+ </div>
+ </div>
+</dialog>
+```
+
+ 4. Code a `<button>` element with `data-action="close"` and `class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect"` to display the close button. Add an `<i>` element inside the `<button>` element to hold the close icon.
+```html
+<dialog class="mdlext-dialog">
+ <div class="mdlext-lightbox mdlext-js-lightbox mdl-card">
+ <div class="mdl-card__menu mdl-color-text--white mdl-typography--body-2-color-contrast">
+ <button data-action="close" class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect" title="Close">
+ <i class="material-icons">close</i>
+ </button>
+ </div>
+ </div>
+</dialog>
+```
+
+ 5. Code a `<figure>` element with `class="mdl-card__media"` to hold the image and the image description.
+```html
+<dialog class="mdlext-dialog">
+ <div class="mdlext-lightbox mdlext-js-lightbox mdl-card">
+ <div class="mdl-card__menu mdl-color-text--white mdl-typography--body-2-color-contrast">
+ <button data-action="close" class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect" title="Close">
+ <i class="material-icons">close</i>
+ </button>
+ </div>
+ <figure class="mdl-card__media">
+ </figure>
+ </div>
+</dialog>
+```
+
+ 5. Inside the `<figure>` element code an empty `<img>` element and an empty `<figcaption>` element to hold the image and the image description.
+```html
+<dialog class="mdlext-dialog">
+ <div class="mdlext-lightbox mdlext-js-lightbox mdl-card">
+ <div class="mdl-card__menu mdl-color-text--white mdl-typography--body-2-color-contrast">
+ <button data-action="close" class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect" title="Close">
+ <i class="material-icons">close</i>
+ </button>
+ </div>
+ <figure class="mdl-card__media">
+ <img src="" alt>
+ <figcaption></figcaption>
+ </figure>
+ </div>
+</dialog>
+```
+
+
+ 6. Code a `<footer>` element with `class="mdl-card__actions"` to hold the image title and navigation buttons.
+```html
+<dialog class="mdlext-dialog">
+ <div class="mdlext-lightbox mdlext-js-lightbox mdl-card">
+ <div class="mdl-card__menu mdl-color-text--white mdl-typography--body-2-color-contrast">
+ <button data-action="close" class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect" title="Close">
+ <i class="material-icons">close</i>
+ </button>
+ </div>
+ <figure class="mdl-card__media">
+ <img src="" alt>
+ <figcaption></figcaption>
+ </figure>
+ <footer class="mdl-card__actions">
+ </footer>
+ </div>
+</dialog>
+```
+
+ 7. Code a `<div>` element with `class="mdl-card__supporting-text"` to hold the image title.
+```html
+<dialog class="mdlext-dialog">
+ <div class="mdlext-lightbox mdlext-js-lightbox mdl-card">
+ <div class="mdl-card__menu mdl-color-text--white mdl-typography--body-2-color-contrast">
+ <button data-action="close" class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect" title="Close">
+ <i class="material-icons">close</i>
+ </button>
+ </div>
+ <figure class="mdl-card__media">
+ <img src="" alt>
+ <figcaption></figcaption>
+ </figure>
+ <footer class="mdl-card__actions">
+ <div class="mdl-card__supporting-text">
+ </div>
+ </footer>
+ </div>
+</dialog>
+```
+
+ 8. Code a `<nav>` element to hold the navigation buttons.
+```html
+<dialog class="mdlext-dialog">
+ <div class="mdlext-lightbox mdlext-js-lightbox mdl-card">
+ <div class="mdl-card__menu mdl-color-text--white mdl-typography--body-2-color-contrast">
+ <button data-action="close" class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect" title="Close">
+ <i class="material-icons">close</i>
+ </button>
+ </div>
+ <figure class="mdl-card__media">
+ <img src="" alt>
+ <figcaption></figcaption>
+ </figure>
+ <footer class="mdl-card__actions mdl-card--border">
+ <div class="mdl-card__supporting-text">
+ </div>
+ <nav>
+ </nav>
+ </footer>
+ </div>
+</dialog>
+```
+
+
+ 9. Add your navigation buttons with `class="mdl-button mdl-button--icon mdl-js-button mdl-js-ripple-effect"` inside the `<nav>` element.
+```html
+<dialog class="mdlext-dialog">
+ <div class="mdlext-lightbox mdlext-js-lightbox mdl-card">
+ <div class="mdl-card__menu mdl-color-text--white mdl-typography--body-2-color-contrast">
+ <button data-action="close" class="mdl-button mdl-button--icon mdl-js-button" title="Close">
+ <i class="material-icons">close</i>
+ </button>
+ </div>
+ <figure class="mdl-card__media">
+ <img src="" alt>
+ <figcaption></figcaption>
+ </figure>
+ <footer class="mdl-card__actions mdl-card--border">
+ <div class="mdl-card__supporting-text">
+ </div>
+ <nav>
+ <button data-action="first" class="mdl-button mdl-button--icon mdl-js-button" title="First">
+ <i class="material-icons">first_page</i>
+ </button>
+ <button data-action="prev" class="mdl-button mdl-button--icon mdl-js-button" title="Previous">
+ <i class="material-icons">chevron_left</i>
+ </button>
+ <button data-action="next" class="mdl-button mdl-button--icon mdl-js-button" title="Next">
+ <i class="material-icons">chevron_right</i>
+ </button>
+ <button data-action="last" class="mdl-button mdl-button--icon mdl-js-button" title="Last">
+ <i class="material-icons">last_page</i>
+ </button>
+ </nav>
+ </footer>
+ </div>
+</dialog>
+```
+Add as many buttons as you like. To identify the button that trigger an custom event, you should assign each button a unique data-action attribute value.
+The data-action attribute will be emitted as a part of the custom event triggered when a button is clicked.
+
+ 10. Add an image and open the dialog.
+
+```javascript
+var dialog = document.querySelector('dialog');
+
+// A dialog element MUST be a child of document.body!!
+if(dialog.parentNode.tagName !== 'BODY') {
+ document.body.appendChild(dialog);
+}
+
+if (!('showModal' in dialog)) {
+ dialogPolyfill.registerDialog(dialog);
+}
+var lightbox = dialog.querySelector('.mdlext-lightbox');
+var img = lightbox.querySelector('img');
+var supportingText = lightbox.querySelector('.mdl-card__supporting-text');
+var imageDetails = lightbox.querySelector('figcaption');
+
+img.setAttribute("src", 'wiew-from-my-window.jpg');
+img.setAttribute("alt", 'View from my window');
+img.setAttribute("title", 'View from my window');
+img.setAttribute('data-img-url-prev', 'some-image.jpg');
+img.setAttribute('data-img-url-next', 'some-other-image.jpg');
+supportingText.innerHTML = 'View from my window';
+imageDetails.innerHTML = 'Photo taken from my window yesterday morning';
+
+if(!dialog.open) {
+ dialog.showModal();
+}
+```
+
+### Examples
+* See: [snippets/carousel.html](./snippets/lightbox.html)
+* TRy out [the live demo](http://leifoolsen.github.io/mdl-ext/demo/lightbox.html)
+
+## Keyboard interaction
+The lightbox interacts with the following keyboard keys.
+
+* `Left arrow` - Emits a custom event with action='prev'
+* `Right arrow` - Emits a custom event with action='next'
+* `Up arrow` - behaves the same as left arrow.
+* `Down arrow` - behaves the same as right arrow.
+* `End` - Emits a custom event with action='last'
+* `Home` - Emits a custom event with action='first'
+* `Space` - Emits a custom event with action='select'
+* `Esc` - Emits a custom event with action='cancel'
+
+## Mouse / Touch interaction
+* `Drag/Swipe left` - Emits a custom event with action='next'
+* `Drag/Swipe right` - Emits a custom event with action='prev'
+
+## Events
+The lightbox emits a custom **action** event when a button contained in the lightbox is clicked, an images is dragged or swiped,
+or if one of the keys `Arrow Left`, `Arrow Up`, `Arrow Right`, `Arrow Down`, `Home`, `End`, `Space` or `Esc` is pressed.
+The event has a detail object with the following content:
+```
+{
+ action, // one of: 'first', 'prev', 'next', 'last', 'select', 'close', 'cancel' -
+ // or any value assigned to a button action attribute (empty string if no action assigned)
+ source // the button instance that caused the event, or the lightbox element if a key triggered the event
+}
+```
+
+## Configuration options
+
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements to the lightbox.
+The table below lists the available classes and their effects.
+
+| MDLEXT class | Effect | Remarks |
+|--------------|--------|---------|
+| `mdlext-lightbox` | Defines a container as an MDLEXT lightbox component | Required on `<div>` element |
+| `mdlext-js-lightbox` | Assigns basic MDL behavior to lightbox | Required on `<div>` element |
+| `mdlext-lightbox__slider` | Displays previous, current and next image when dragging | Element added by component |
+| `mdlext-lightbox__slider__slide` | Holds an image to display when dragging | Element added by component |
+
+<!--
+| `mdlext-lightbox--sticky-footer` | Positions footer at bottom of screen | Optional on `mdlext-lightbox` element |
+-->
+
+| Attribute | Effect | Remarks |
+|-----------|--------|---------|
+| `data-img-url-prev` | Displays previous image when dragging | URL to previous image in a collection |
+| `data-img-url-next` | Displays next image when dragging | URL to next imagein a collection |
+
+
+## How to use the component programmatically
+The [tests](../../test/lightbox/lightbox.spec.js) and the [snippets/lightbox.html](./snippets/lightbox.html)
+code provides examples on how to use the component programmatically.
+
diff --git a/node_modules/mdl-ext/src/lightbox/snippets/lightbox.html b/node_modules/mdl-ext/src/lightbox/snippets/lightbox.html
new file mode 100644
index 0000000..095da06
--- /dev/null
+++ b/node_modules/mdl-ext/src/lightbox/snippets/lightbox.html
@@ -0,0 +1,553 @@
+<p>A lightbox displays an image filling the screen, and dimming out the rest of the web page. It acts as a modal dialog
+ using the <code><dialog></code> element as a container for the lightbox.
+ <strong>Click on one of the images to open the lightbox. Browse images in the lightbox using arrow keys, clicking on
+ one of the navigation buttons, or by dragging or swiping the image.</strong>
+</p>
+
+<!--
+ This example uses the data-details attribute to feed data to the lightbox.
+ Use any data structure that suits you to feed the lightbox.
+ The a element holds reference to lightbox image
+ -->
+<ul id="lightboard-for-lightbox" class="mdlext-lightboard mdlext-js-lightboard mdl-js-ripple-effect mdl-js-ripple-effect--ignore-events">
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Northern goshawk with prey' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' },
+ { 'name': 'Camera', 'value': 'Nikon D800E' },
+ { 'name': 'Lens', 'value': 'Nikkor 300mm/4 PF' },
+ { 'name': 'Converter', 'value': 'TC14-II' },
+ { 'name': 'Focal length', 'value': '420mm' },
+ { 'name': 'Aperture', 'value': 'f/7.1' },
+ { 'name': 'Shutter speed', 'value': '1/400s' }]" >
+ <a href="./images/_D802141.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D802141.jpg" title="Northern goshawk with prey"/>
+ <figcaption>_D802141.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Northern goshawk with prey' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' },
+ { 'name': 'Camera', 'value': 'Nikon D800E' },
+ { 'name': 'Lens', 'value': 'Nikkor 300mm/4 PF' },
+ { 'name': 'Converter', 'value': 'TC14-II' },
+ { 'name': 'Focal length', 'value': '420mm' },
+ { 'name': 'Aperture', 'value': 'f/7.1' },
+ { 'name': 'Shutter speed', 'value': '1/400s' }]" >
+ <a href="./images/_D802143-2.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D802143.jpg" title="Northern goshawk with prey"/>
+ <figcaption>_D802143.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Whooper swans in flight' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]">
+ <a href="./images/_D802591.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D802591.jpg" title="Whooper swans in flight"/>
+ <figcaption>_D802591.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'European green woodpecker' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]">
+ <a href="./images/_D804370-3.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D804370-3.jpg" title="European green woodpecker"/>
+ <figcaption>_D804370-3.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'The bridge' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="./images/_D808689.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D808689.jpg" title="The bridge"/>
+ <figcaption>_D808689.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Landscape in blue pastel' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="./images/_D802181.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D802181.jpg" title="Landscape in blue pastel"/>
+ <figcaption>_D802181.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Hiking the mountains of Dovre' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="./images/_D800912.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800912.jpg" title="Hiking the mountains of Dovre"/>
+ <figcaption>_D800912.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'The Polar Express, end of Line. Ny Aalesund, Spitsbergen' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="./images/_D809453-_D809457-3.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D809453-_D809457-4.jpg" title="The Polar Express, end of Line" />
+ <figcaption>_D809453-_D809457-4.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Still got the blues' },
+ { 'name': 'Description', 'value': 'PULSE, Kilden Consert Hall, Kristiansand' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="./images/_DSC8214-2.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_DSC8214.jpg" title="Still got the blues"/>
+ <figcaption>_DSC8214.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Flowers' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="./images/_D800017.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800017.jpg" />
+ <figcaption>_D800017.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Red-breasted merganser' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="./images/_D800023.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800023.jpg" />
+ <figcaption>_D800023.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Musk oxes, Dovre, Norway' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="./images/_D800851.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800851.jpg" />
+ <figcaption>_D800851.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Arctic Fox, Svalbard, Norway' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="./images/_D800166-2.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800166.jpg" />
+ <figcaption>_D800166.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Fly fishing the arctic waters, Svalbard, Norway' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800951.jpg" />
+ <figcaption>_D800951.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Lady of the snows (Pulsatilla vernalis), Dovre, Norway' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' },
+ { 'name': 'Camera', 'value': 'Nikon D800E' },
+ { 'name': 'Lens', 'value': 'Nikkor 400mm/2.8GEDVR' },
+ { 'name': 'Converter', 'value': 'TC1.4II' },
+ { 'name': 'Focal length', 'value': '550mm' },
+ { 'name': 'Aperture', 'value': 'f/8' },
+ { 'name': 'Shutter speed', 'value': '1/200s' }
+ ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D801188.jpg" />
+ <figcaption>_D801188.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'PULSE, Kilden Consert Hall, Kristiansand' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D801205-2.jpg" />
+ <figcaption>_D801205-2.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'PULSE, Kilden Consert Hall, Kristiansand' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D801274.jpg" />
+ <figcaption>_D801274.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Peregrine falcon, Norway' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D801392.jpg" />
+ <figcaption>_D801392.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Peregrine falcon, Norway' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' },
+ { 'name': 'Camera', 'value': 'Nikon D800E' },
+ { 'name': 'Lens', 'value': 'Nikkor 400mm/2.8GEDVR' },
+ { 'name': 'Focal length', 'value': '400mm' },
+ { 'name': 'Aperture', 'value': 'f/2.8' },
+ { 'name': 'Shutter speed', 'value': '1/800s' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D801436.jpg" />
+ <figcaption>_D801392.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Mr. Per E Knudsen' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D801952-4.jpg" />
+ <figcaption>_D801952-4.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Black Woodpecker' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D807603.jpg" />
+ <figcaption>_D807603.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Goshina' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D807689.jpg" />
+ <figcaption>_D807689.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Goshina' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D807558.jpg" />
+ <figcaption>_D807689.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Svalbard Rock ptarmigan' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' }]" >
+ <a href="./images/_D800464.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800464.jpg" />
+ <figcaption>_D800464.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Nice, France' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="./images/_DSC7535-2.jpg" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_DSC7535.jpg" />
+ <figcaption>_DSC7535.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Cheetah, Bloemfontain, South Africa' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D802478.jpg" />
+ <figcaption>_D802478.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Red Squirrel' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D800698.jpg" />
+ <figcaption>_D800698.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Milky Way, Bloemfontain, South Africa' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' },
+ { 'name': 'Camera', 'value': 'Nikon D800E' },
+ { 'name': 'Lens', 'value': 'Nikkor 20mm/1.8' },
+ { 'name': 'Focal length', 'value': '20mm' },
+ { 'name': 'Aperture', 'value': 'f/2.0' },
+ { 'name': 'Shutter speed', 'value': '15s' },
+ { 'name': 'ISO', 'value': '1600' }]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D803118.jpg" />
+ <figcaption>_D803118.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Winter Light, Senja, Norway' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D803521.jpg" />
+ <figcaption>_D803521.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Selfie with Aurora B :)' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D803465-3.jpg" />
+ <figcaption>_D803465-3.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Lista Lighthouse, Norway' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' },
+ { 'name': 'Camera', 'value': 'Nikon D800E' },
+ { 'name': 'Lens', 'value': 'Nikkor 16mm/2.8D Fisheye' },
+ { 'name': 'Focal length', 'value': '16mm' },
+ { 'name': 'Aperture', 'value': 'f/8' },
+ { 'name': 'Shutter speed', 'value': '1/20s' },
+ { 'name': 'ISO', 'value': '100' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D806374.jpg" />
+ <figcaption>_D803465-3.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+ <li class="mdlext-lightboard__slide" data-details="[
+ { 'name': 'Title', 'value': 'Osprey' },
+ { 'name': 'Copyright ©', 'value': 'Leif Olsen' },
+ { 'name': 'Camera', 'value': 'Nikon D800E' },
+ { 'name': 'Lens', 'value': 'Nikkor 400mm/2.8GEDVR' },
+ { 'name': 'Converter', 'value': 'TC1.4II' },
+ { 'name': 'Focal length', 'value': '550mm' },
+ { 'name': 'Aperture', 'value': 'f/5.6' },
+ { 'name': 'Shutter speed', 'value': '1/400s' } ]" >
+ <a href="#" class="mdlext-lightboard__slide__frame">
+ <figure>
+ <img src="./images/_D805345-12.jpg" />
+ <figcaption>_D805345-12.jpg</figcaption>
+ </figure>
+ </a>
+ </li>
+</ul>
+
+<p class="mdl-typography--caption" style="margin-top: 32px;">
+ All images appearing in this page are the exclusive property of Leif Olsen and are protected under the United States
+ and International Copyright laws. The images may not be reproduced or manipulated without the written permission of
+ Leif Olsen. Use of any image as the basis for another photographic concept or illustration (digital, artist rendering
+ or alike) is a violation of the United States and International Copyright laws. All images are copyrighted © Leif Olsen, 2016.
+</p>
+
+
+<!-- A dialog element MUST be a child of document.body!! -->
+<dialog id="lightbox-dialog" class="mdlext-dialog">
+
+ <div id="lightbox" class="mdlext-lightbox mdlext-js-lightbox mdl-card mdl-shadow--4dp">
+ <div class="mdl-card__menu mdl-color-text--white mdl-typography--body-2-color-contrast">
+ <button data-action="close" class="mdl-button mdl-button--icon mdl-js-button" title="Close">
+ <i class="material-icons">close</i>
+ </button>
+ </div>
+ <figure class="mdl-card__title">
+ <img src="" draggable="true" alt>
+ <figcaption data-action="select">Details</figcaption>
+ </figure>
+ <footer data-action="select" class="mdl-card__actions mdl-card--border">
+ <div class="mdl-card__supporting-text">
+ Image title
+ </div>
+ <nav>
+ <button data-action="first" class="mdl-button mdl-button--icon mdl-js-button" title="First">
+ <i class="material-icons">first_page</i>
+ </button>
+ <button data-action="prev" class="mdl-button mdl-button--icon mdl-js-button" title="Previous">
+ <i class="material-icons">chevron_left</i>
+ </button>
+ <button data-action="next" class="mdl-button mdl-button--icon mdl-js-button" title="Next">
+ <i class="material-icons">chevron_right</i>
+ </button>
+ <button data-action="last" class="mdl-button mdl-button--icon mdl-js-button" title="Last">
+ <i class="material-icons">last_page</i>
+ </button>
+ <button data-action="select" class="mdl-button mdl-button--icon mdl-js-button" title="Details">
+ <i class="material-icons">info_outline</i>
+ </button>
+ </nav>
+ </footer>
+ </div>
+</dialog>
+
+<script>
+ window.addEventListener('load', function() {
+ var dialog = document.querySelector('#lightbox-dialog');
+
+ // A dialog element MUST be a child of document.body!!
+ // In a SPA you should choose a more robust strategy than the simple if provided here
+ if(dialog.parentNode.tagName !== 'BODY') {
+ document.body.appendChild(dialog);
+ }
+
+ if (!('showModal' in dialog)) {
+ dialogPolyfill.registerDialog(dialog);
+ }
+
+ var currentSlide = null;
+ var lightboard = document.querySelector('#lightboard-for-lightbox');
+ var slides = lightboard.querySelectorAll('.mdlext-lightboard__slide');
+
+ lightboard.addEventListener('select', function(e) {
+ currentSlide = e.detail.source;
+ for (var i = 0, n = slides.length; i < n; i++) {
+ if(currentSlide === slides[i]) {
+ break;
+ }
+ }
+ var prevSlide = slides[ i > 0 ? i-1 : n-1 ];
+ var nextSlide = slides[ i < n-1 ? i+1 : 0];
+ showImage(currentSlide, prevSlide, nextSlide);
+ });
+
+ var lightbox = dialog.querySelector('.mdlext-lightbox');
+
+ lightbox.addEventListener('action', function(e) {
+ if(e.detail.action === 'close') {
+ dialog.close();
+ }
+ else if(e.detail.action === 'select') {
+ var figcaption = lightbox.querySelector('figure figcaption');
+ if(figcaption.classList.contains('mdlext-lightbox__show-figcaption')) {
+ figcaption.classList.remove('mdlext-lightbox__show-figcaption');
+ }
+ else {
+ figcaption.classList.add('mdlext-lightbox__show-figcaption');
+ }
+ }
+ else {
+ var i = 0;
+ var n = slides.length
+
+ if(e.detail.action === 'first') {
+ currentSlide = slides[0];
+ }
+ else if(e.detail.action === 'prev' || e.detail.action === 'next') {
+ for (var j = 0; j < n; j++) {
+ if(currentSlide === slides[j]) {
+ if(e.detail.action === 'prev') {
+ i = j > 0 ? j-1 : n-1;
+ currentSlide = slides[i];
+ }
+ else if(e.detail.action === 'next') {
+ i = j < n-1 ? j+1 : 0;
+ currentSlide = slides[i];
+ }
+ break;
+ }
+ }
+ }
+ else if(e.detail.action === 'last') {
+ i = slides.length-1;
+ currentSlide = slides[i];
+ }
+ var prevSlide = slides[ i > 0 ? i-1 : n-1 ];
+ var nextSlide = slides[ i < n-1 ? i+1 : 0];
+ showImage(currentSlide, prevSlide, nextSlide);
+ }
+ });
+
+ function showImage(slide, prevSlide, nextSlide) {
+
+ var slideAnchor = slide.querySelector('a');
+ var slideImg = slide.querySelector('img');
+ var img = dialog.querySelector('img');
+ var supportingText = dialog.querySelector('.mdl-card__supporting-text');
+ var imageDetails = dialog.querySelector('figcaption');
+ var href = slideAnchor.getAttribute('href');
+ href = href && href.indexOf('#') === 0 ? slideImg.getAttribute('src') : href;
+ img.setAttribute('src', href);
+ img.setAttribute('alt', slideImg.getAttribute('title') || '');
+ img.setAttribute('title', slideImg.getAttribute('title') || '');
+ supportingText.innerHTML = slideImg.getAttribute('title') || '';
+
+ // Lazy coder :)
+ slideAnchor = prevSlide.querySelector('a');
+ slideImg = prevSlide.querySelector('img');
+ href = slideAnchor.getAttribute('href');
+ href = href && href.indexOf('#') === 0 ? slideImg.getAttribute('src') : href;
+ img.setAttribute('data-img-url-prev', href);
+
+ slideAnchor = nextSlide.querySelector('a');
+ slideImg = nextSlide.querySelector('img');
+ href = slideAnchor.getAttribute('href');
+ href = href && href.indexOf('#') === 0 ? slideImg.getAttribute('src') : href;
+ img.setAttribute('data-img-url-next', href);
+
+
+ var detailsHtml = '';
+ var detailsArray = JSON.parse(slide.getAttribute('data-details').replace(/'/g, '"'));
+
+ if(detailsArray != null) {
+ detailsHtml = '<table><tbody>';
+ for (var i = 0, n = detailsArray.length; i < n; i++) {
+ detailsHtml += '<tr><th>' + detailsArray[i].name + '</th><td>' + detailsArray[i].value + '</td></tr>';
+
+ if(!supportingText.innerHTML && detailsArray[i].name.toLowerCase() === 'title') {
+ supportingText.innerHTML = detailsArray[i].value;
+ }
+ }
+ detailsHtml += '</tbody></table>';
+ }
+
+ imageDetails.innerHTML = '';
+ imageDetails.insertAdjacentHTML('afterbegin', detailsHtml);
+
+ if(!dialog.open) {
+ dialog.showModal();
+ }
+ }
+ });
+</script>
diff --git a/node_modules/mdl-ext/src/mdl-ext-build.scss b/node_modules/mdl-ext/src/mdl-ext-build.scss
new file mode 100644
index 0000000..beda184
--- /dev/null
+++ b/node_modules/mdl-ext/src/mdl-ext-build.scss
@@ -0,0 +1,8 @@
+@charset "UTF-8";
+
+// Material Design Lite
+@import '~material-design-lite/src/variables';
+@import '~material-design-lite/src/mixins';
+
+// mdl-ext
+@import 'mdl-ext';
diff --git a/node_modules/mdl-ext/src/mdl-ext-eqjs-build.scss b/node_modules/mdl-ext/src/mdl-ext-eqjs-build.scss
new file mode 100644
index 0000000..f321f90
--- /dev/null
+++ b/node_modules/mdl-ext/src/mdl-ext-eqjs-build.scss
@@ -0,0 +1,8 @@
+@charset "UTF-8";
+
+// Material Design Lite
+@import '~material-design-lite/src/variables';
+@import '~material-design-lite/src/mixins';
+
+// mdl-ext
+@import 'mdl-ext-eqjs';
diff --git a/node_modules/mdl-ext/src/mdl-ext-eqjs.scss b/node_modules/mdl-ext/src/mdl-ext-eqjs.scss
new file mode 100644
index 0000000..56af48f
--- /dev/null
+++ b/node_modules/mdl-ext/src/mdl-ext-eqjs.scss
@@ -0,0 +1,39 @@
+@charset "UTF-8";
+
+/**
+ * Element Queries are a new way of writing CSS styles so the rules apply to individual elements
+ * on the page, instead of to the whole page as one document like in regular CSS Media Queries.
+ * This SASS file includes the eq.js, https://github.com/Snugug/eq.js, prolyfill which is an easy to use
+ * drop-in solution to JavaScript powered element queries. It works well with SASS,
+ * and element queries work without requireing a server to run.
+ *
+ * Feel fre to write your own element query stylesheet using one of the other libraries, e.g:
+ * [EQCSS] - (https://github.com/eqcss/eqcss)
+ * [CSS Element Queries] - (https://github.com/marcj/css-element-queries)
+ * [BoomQueries] - (https://github.com/BoomTownROI/boomqueries)
+ */
+
+// eq.js mixins
+@import '~eq.js/sass/eq';
+
+// Configuration and helpers
+@import 'variables';
+@import 'mixins';
+@import 'functions';
+
+// Components
+@import 'aria-expanded-toggle/aria-expanded-toggle';
+@import 'sticky-header/sticky-header';
+@import 'dialog/dialog';
+@import 'grid/grid-eqjs';
+@import 'lightboard/lightboard';
+@import 'lightboard/lightboard-eqjs';
+@import 'lightbox/lightbox';
+@import 'carousel/carousel';
+@import 'selectfield/selectfield';
+@import 'menu-button/menu-button';
+@import 'bordered-fields/bordered-fields';
+@import 'collapsible/collapsible';
+@import 'accordion/accordion';
+@import 'color-themes/light-color-theme';
+@import 'color-themes/dark-color-theme';
diff --git a/node_modules/mdl-ext/src/mdl-ext.scss b/node_modules/mdl-ext/src/mdl-ext.scss
new file mode 100644
index 0000000..0f57eb2
--- /dev/null
+++ b/node_modules/mdl-ext/src/mdl-ext.scss
@@ -0,0 +1,23 @@
+@charset "UTF-8";
+
+// Configuration and helpers
+@import 'variables';
+@import 'mixins';
+@import 'functions';
+
+// Components
+@import 'aria-expanded-toggle/aria-expanded-toggle';
+@import 'sticky-header/sticky-header';
+@import 'dialog/dialog';
+@import 'grid/grid-media-queries';
+@import 'lightboard/lightboard';
+@import 'lightboard/lightboard-media-queries';
+@import 'lightbox/lightbox';
+@import 'carousel/carousel';
+@import 'selectfield/selectfield';
+@import 'menu-button/menu-button';
+@import 'bordered-fields/bordered-fields';
+@import 'collapsible/collapsible';
+@import 'accordion/accordion';
+@import 'color-themes/light-color-theme';
+@import 'color-themes/dark-color-theme';
diff --git a/node_modules/mdl-ext/src/menu-button/_menu-button.scss b/node_modules/mdl-ext/src/menu-button/_menu-button.scss
new file mode 100644
index 0000000..9fd84d4
--- /dev/null
+++ b/node_modules/mdl-ext/src/menu-button/_menu-button.scss
@@ -0,0 +1,181 @@
+@charset "UTF-8";
+
+/**
+ * @license
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+/* Moved to aria-expanded-toggle.scss
+
+.mdlext-aria-expanded-plus-minus {
+ @include mdlext-aria-expanded-toggle($font-family: inherit);
+}
+
+.mdlext-aria-expanded-more-less {
+ @include mdlext-aria-expanded-toggle($icon: 'expand_more', $icon-expanded: 'expand_less');
+}
+*/
+
+.mdlext-menu-button {
+ box-sizing: border-box;
+ @include typo-menu();
+ text-transform: none;
+ position: relative;
+ height: $button-height;
+ padding: 0 $button-padding;
+ display: flex;
+ align-items: center;
+ align-self: stretch;
+
+ > * {
+ margin: 0;
+ padding: 0 0 0 8px;
+ }
+
+ > *:first-child {
+ padding-left: 0;
+ }
+
+ > *:last-child:not(:only-child):not(.mdlext-menu__item__caption) {
+ margin-left: auto; // If more than one element, push last element to the right
+ }
+
+}
+
+.mdlext-menu-button__caption {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ line-height: 1.2;
+}
+
+.mdlext-menu,
+.mdlext-menu__item {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ display: flex;
+}
+
+.mdlext-menu {
+ position: absolute; //fixed;
+ background: $default-dropdown-bg-color;
+ z-index: 1000;
+ min-width: 124px;
+ border-radius: 2px;
+ @include shadow-3dp();
+ display: inline-flex;
+ flex-direction: column;
+ padding: 0;
+ overflow: hidden;
+ overflow-y: auto;
+
+ &:focus {
+ outline-offset: -1px;
+ outline-width: 1px;
+ }
+
+ &[hidden] {
+ @include mdlext-visually-hidden;
+ pointer-events: none;
+ }
+
+ &__item {
+ @include typo-body-1();
+ color: $default-item-text-color;
+ background-color: $default-dropdown-bg-color;
+ position: relative;
+ padding: 0 16px 0 24px;
+ align-items: center;
+ align-self: stretch;
+ text-decoration: none;
+ cursor: pointer;
+ white-space: nowrap;
+ user-select: none;
+ min-height: 40px;
+ overflow: hidden;
+
+ &[aria-selected='true'] {
+ background-color: $default-item-active-bg-color;
+ }
+
+ // checkmark
+ &[aria-selected='true']::before {
+ content:'\2713';
+ position: absolute;
+ font-size: 1.4em;
+ left: 4px;
+ top: 50%;
+ transform: translateY(-50%);
+ pointer-events: none;
+ }
+
+ &:hover:not([disabled]) {
+ background-color: $default-item-hover-bg-color;
+ }
+
+ &:focus {
+ outline-offset: -2px;
+ outline-width: 1px;
+ outline-color: $default-item-outline-color;
+ background-color: $default-item-focus-bg-color;
+ }
+
+ &::-moz-focus-inner {
+ border: 0;
+ }
+
+ &[disabled] {
+ color: $disabled-item-text-color;
+ background-color: transparent;
+ cursor: auto;
+ pointer-events: none;
+
+ > * {
+ color: $disabled-item-text-color;
+ }
+ }
+
+ &__caption {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ > * {
+ margin: 0;
+ padding: 0 0 0 8px;
+ }
+
+ > *:first-child {
+ padding-left: 0;
+ }
+
+ > *:last-child:not(:only-child):not(.mdlext-menu__item__caption) {
+ margin-left: auto; // If more than one element, push last element to the right
+ }
+
+ }
+ &__item-separator {
+ margin: 0;
+ padding: 0;
+ border-bottom: 1px solid $default-item-divider-color;
+ }
+
+}
diff --git a/node_modules/mdl-ext/src/menu-button/menu-button.js b/node_modules/mdl-ext/src/menu-button/menu-button.js
new file mode 100644
index 0000000..e7e37d8
--- /dev/null
+++ b/node_modules/mdl-ext/src/menu-button/menu-button.js
@@ -0,0 +1,758 @@
+/**
+ * @license
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+
+/**
+ * A menu button is a button that opens a menu. It is often styled as a
+ * typical push button with a downward pointing arrow or triangle to hint
+ * that activating the button will display a menu.
+ */
+import { randomString } from '../utils/string-utils';
+import fullThrottle from '../utils/full-throttle';
+import {
+ VK_TAB,
+ VK_ENTER,
+ VK_ESC,
+ VK_SPACE,
+ VK_END,
+ VK_HOME,
+ VK_ARROW_LEFT,
+ VK_ARROW_UP,
+ VK_ARROW_RIGHT,
+ VK_ARROW_DOWN,
+ IS_UPGRADED,
+} from '../utils/constants';
+
+import { getScrollParents, tether } from '../utils/dom-utils';
+
+const JS_MENU_BUTTON = 'mdlext-js-menu-button';
+const MENU_BUTTON_MENU = 'mdlext-menu';
+const MENU_BUTTON_MENU_ITEM = 'mdlext-menu__item';
+const MENU_BUTTON_MENU_ITEM_SEPARATOR = 'mdlext-menu__item-separator';
+//const MDL_LAYOUT_CONTENT = 'mdl-layout__content';
+
+/**
+ * Creates the menu controlled by the menu button
+ * @param element
+ * @return {{element: Element, selected: Element, open: (function(*=)), removeListeners: (function()), downgrade: (function())}}
+ */
+
+const menuFactory = element => {
+
+ let ariaControls = null;
+ let parentNode = null;
+
+ const removeAllSelected = () => {
+ [...element.querySelectorAll(`.${MENU_BUTTON_MENU_ITEM}[aria-selected="true"]`)]
+ .forEach(selectedItem => selectedItem.removeAttribute('aria-selected'));
+ };
+
+ const setSelected = (item, force=false) => {
+ if(force || (item && !item.hasAttribute('aria-selected'))) {
+ removeAllSelected();
+ if(item) {
+ item.setAttribute('aria-selected', 'true');
+ }
+ }
+ };
+
+ const getSelected = () => {
+ return element.querySelector(`.${MENU_BUTTON_MENU_ITEM}[aria-selected="true"]`);
+ };
+
+ const isDisabled = item => item && item.hasAttribute('disabled');
+
+ const isSeparator = item => item && item.classList.contains(MENU_BUTTON_MENU_ITEM_SEPARATOR);
+
+ const focus = item => {
+ if(item) {
+ item = item.closest(`.${MENU_BUTTON_MENU_ITEM}`);
+ }
+ if(item) {
+ item.focus();
+ }
+ };
+
+ const nextItem = current => {
+ let n = current.nextElementSibling;
+ if(!n) {
+ n = element.firstElementChild;
+ }
+ if(!isDisabled(n) && !isSeparator(n)) {
+ focus(n);
+ }
+ else {
+ let i = element.children.length;
+ while(n && i-- > 0) {
+ if(isDisabled(n) || isSeparator(n)) {
+ n = n.nextElementSibling;
+ if(!n) {
+ n = element.firstElementChild;
+ }
+ }
+ else {
+ focus(n);
+ break;
+ }
+ }
+ }
+ };
+
+ const previousItem = current => {
+ let p = current.previousElementSibling;
+ if(!p) {
+ p = element.lastElementChild;
+ }
+ if(!isDisabled(p) && !isSeparator(p)) {
+ focus(p);
+ }
+ else {
+ let i = element.children.length;
+ while(p && i-- > 0) {
+ if(isDisabled(p) || isSeparator(p)) {
+ p = p.previousElementSibling;
+ if(!p) {
+ p = element.lastElementChild;
+ }
+ }
+ else {
+ focus(p);
+ break;
+ }
+ }
+ }
+ };
+
+ const firstItem = () => {
+ const item = element.firstElementChild;
+ if(isDisabled(item) || isSeparator(item) ) {
+ nextItem(item);
+ }
+ else {
+ focus(item);
+ }
+ };
+
+ const lastItem = () => {
+ const item = element.lastElementChild;
+ if(isDisabled(item) || isSeparator(item)) {
+ previousItem(item);
+ }
+ else {
+ focus(item);
+ }
+ };
+
+ const selectItem = item => {
+ if(item && !isDisabled(item) && !isSeparator(item)) {
+ setSelected(item);
+ close(true, item);
+ }
+ };
+
+ const keyDownHandler = event => {
+
+ const item = event.target.closest(`.${MENU_BUTTON_MENU_ITEM}`);
+
+ switch (event.keyCode) {
+ case VK_ARROW_UP:
+ case VK_ARROW_LEFT:
+ if(item) {
+ previousItem(item);
+ }
+ else {
+ firstItem();
+ }
+ break;
+
+ case VK_ARROW_DOWN:
+ case VK_ARROW_RIGHT:
+ if(item) {
+ nextItem(item);
+ }
+ else {
+ lastItem();
+ }
+ break;
+
+ case VK_HOME:
+ firstItem();
+ break;
+
+ case VK_END:
+ lastItem();
+ break;
+
+ case VK_SPACE:
+ case VK_ENTER:
+ selectItem(item);
+ break;
+
+ case VK_ESC:
+ close(true);
+ break;
+
+ case VK_TAB:
+ // We do not have a "natural" tab order from menu, so the best we can do is to set focus back to the button
+ close(true);
+ break;
+
+ default:
+ return;
+ }
+ event.preventDefault();
+ };
+
+
+ const blurHandler = event => {
+
+ // See: https://github.com/facebook/react/issues/2011
+ const t = event.relatedTarget ||
+ event.explicitOriginalTarget || // FF
+ document.activeElement; // IE11
+
+ //console.log('***** blur, target, relatedTarget', event.target, t);
+
+ try {
+ if (t) {
+ if (t.closest(`.${MENU_BUTTON_MENU}`) !== element && shouldClose(t)) {
+ close();
+ }
+ }
+ else {
+ close();
+ }
+ }
+ catch(err) {
+ // FF throws error: "TypeError: n.closest is not a function" if related target is a text node
+ close();
+ }
+ };
+
+ const clickHandler = event => {
+ //console.log('***** click, target', event.target);
+
+ event.preventDefault();
+ const t = event.target;
+ if (t && t.closest(`.${MENU_BUTTON_MENU}`) === element) {
+ const item = t.closest(`.${MENU_BUTTON_MENU_ITEM}`);
+ if (item) {
+ selectItem(item);
+ }
+ }
+ else {
+ if (shouldClose(t)) {
+ close();
+ }
+ }
+ };
+
+ const touchStartHandler = event => {
+ //console.log('***** touchStart, target', event.target);
+
+ const t = event.target;
+ if(!(t && t.closest(`.${MENU_BUTTON_MENU}`) === element)) {
+ if (event.type === 'touchstart') {
+ event.preventDefault();
+ }
+ close();
+ }
+ };
+
+ const addListeners = () => {
+ element.addEventListener('keydown', keyDownHandler, false);
+ element.addEventListener('blur', blurHandler, true);
+ element.addEventListener('click', clickHandler, true);
+ document.documentElement.addEventListener('touchstart', touchStartHandler, true);
+ };
+
+ const removeListeners = () => {
+ element.removeEventListener('keydown', keyDownHandler, false);
+ element.removeEventListener('blur', blurHandler, true);
+ element.removeEventListener('click', clickHandler, true);
+ document.documentElement.removeEventListener('touchstart', touchStartHandler, true);
+ };
+
+ const open = (controlElement, position='first') => {
+
+ ariaControls = controlElement.closest(`.${JS_MENU_BUTTON}`);
+
+ element.style['min-width'] = `${Math.max(124, controlElement.getBoundingClientRect().width)}px`;
+ element.removeAttribute('hidden');
+ tether(controlElement, element);
+
+ let item;
+ switch (position.toLowerCase()) {
+ case 'first':
+ firstItem();
+ break;
+
+ case 'last':
+ lastItem();
+ break;
+
+ case 'selected':
+ item = getSelected();
+ if(item && !item.hasAttribute('disabled')) {
+ focus(item);
+ }
+ else {
+ firstItem();
+ }
+ break;
+ }
+
+ addListeners();
+ };
+
+
+ const shouldClose = target => {
+ //console.log('***** shouldClose');
+
+ let result = false;
+ const btn = (target && target.closest(`.${JS_MENU_BUTTON}`)) || null;
+ if(!btn) {
+ result = true;
+ }
+ else if(btn.getAttribute('aria-controls') === element.id) {
+ if(btn !== ariaControls) {
+ result = true;
+ }
+ }
+ else {
+ result = true;
+ }
+ return result;
+ };
+
+ const close = (forceFocus = false, item = null) => {
+ removeListeners();
+
+ element.dispatchEvent(
+ new CustomEvent('_closemenu', {
+ bubbles: true,
+ cancelable: true,
+ detail: { forceFocus: forceFocus, item: item }
+ })
+ );
+ };
+
+ const addWaiAria = () => {
+ if (!element.hasAttribute('id')) {
+ // Generate a random id
+ element.id = `menu-button-${randomString()}`;
+ }
+ element.setAttribute('tabindex', '-1');
+ element.setAttribute('role', 'menu');
+ element.setAttribute('hidden', '');
+
+ [...element.querySelectorAll(`.${MENU_BUTTON_MENU_ITEM}`)].forEach( menuitem => {
+ menuitem.setAttribute('tabindex', '-1');
+ menuitem.setAttribute('role', 'menuitem');
+ });
+
+ [...element.querySelectorAll(`.${MENU_BUTTON_MENU_ITEM_SEPARATOR}`)].forEach( menuitem => {
+ menuitem.setAttribute('role', 'separator');
+ });
+ };
+
+ const init = () => {
+ addWaiAria();
+ parentNode = element.parentNode;
+ element.classList.add('is-upgraded');
+ };
+
+ const downgrade = () => {
+ removeListeners();
+ if(element.parentNode !== parentNode) {
+ parentNode.appendChild(element);
+ }
+ element.classList.remove('is-upgraded');
+ };
+
+ init();
+
+ return {
+ /**
+ * Get the menu element
+ * @returns {Element} the menu element
+ */
+ get element() {
+ return element;
+ },
+
+ /**
+ * Set selected menu item
+ * @param item
+ */
+ set selected(item) {
+ setSelected(item, true);
+ },
+
+ /**
+ * Open menu
+ * @param {Element} controlElement the element where the menu should be aligned to
+ * @param {String} position menuElement item to receive focus after menu element is opened
+ */
+ open: (controlElement, position='first') => open(controlElement, position),
+
+ /**
+ * Remove event listeners.
+ */
+ removeListeners: () => removeListeners(),
+
+ /**
+ * Downgrade menu
+ */
+ downgrade: () => downgrade(),
+ };
+};
+
+
+/**
+ * The menubutton component
+ */
+
+class MenuButton {
+
+ constructor(element) {
+ this.element = element;
+ this.focusElement = undefined;
+ this.focusElementLastScrollPosition = undefined;
+ this.scrollElements = [];
+ this.menu = undefined;
+ this.selectedItem = null;
+ this.init();
+ }
+
+ keyDownHandler = event => {
+ if(!this.isDisabled()) {
+ switch (event.keyCode) {
+ case VK_ARROW_UP:
+ this.openMenu('last');
+ break;
+
+ case VK_ARROW_DOWN:
+ this.openMenu();
+ break;
+
+ case VK_SPACE:
+ case VK_ENTER:
+ this.openMenu('selected');
+ break;
+
+ case VK_ESC:
+ this.closeMenu();
+ break;
+
+ case VK_TAB:
+ this.closeMenu();
+ return;
+
+ default:
+ return;
+ }
+ }
+ //event.stopPropagation();
+ event.preventDefault();
+ };
+
+ clickHandler = () => {
+ if(!this.isDisabled()) {
+ if(this.element.getAttribute('aria-expanded').toLowerCase() === 'true') {
+ this.closeMenu(true);
+ }
+ else {
+ this.openMenu('selected');
+ }
+ }
+ };
+
+ /**
+ * Re-position menu if content is scrolled, window is resized or orientation change
+ * @see https://javascriptweblog.wordpress.com/2015/11/02/of-classes-and-arrow-functions-a-cautionary-tale/
+ */
+ recalcMenuPosition = fullThrottle( () => {
+ const c = this.focusElement.getBoundingClientRect();
+ const dx = this.focusElementLastScrollPosition.left - c.left;
+ const dy = this.focusElementLastScrollPosition.top - c.top;
+ const left = (parseFloat(this.menu.element.style.left) || 0) - dx;
+ const top = (parseFloat(this.menu.element.style.top) || 0) - dy;
+
+ this.menu.element.style.left = `${left}px`;
+ this.menu.element.style.top = `${top}px`;
+ this.focusElementLastScrollPosition = c;
+ });
+
+
+ positionChangeHandler = () => {
+ this.recalcMenuPosition(this);
+ };
+
+ closeMenuHandler = event => {
+ if(event && event.detail) {
+ if(event.detail.item && event.detail.item !== this.selectedItem) {
+ this.selectedItem = event.detail.item;
+ this.dispatchMenuSelect();
+ }
+ this.closeMenu(event.detail.forceFocus);
+ }
+ };
+
+ dispatchMenuSelect() {
+ this.element.dispatchEvent(
+ new CustomEvent('menuselect', {
+ bubbles: true,
+ cancelable: true,
+ detail: { source: this.selectedItem }
+ })
+ );
+ }
+
+ isDisabled() {
+ return this.element.hasAttribute('disabled');
+ }
+
+ removeListeners() {
+ this.element.removeEventListener('keydown', this.keyDownHandler);
+ this.element.removeEventListener('click', this.clickHandler);
+ }
+
+ openMenu(position='first') {
+
+ if(!this.isDisabled() && this.menu) {
+
+ // Close the menu if button position change
+ this.scrollElements = getScrollParents(this.element);
+ this.scrollElements.forEach(el => el.addEventListener('scroll', this.positionChangeHandler));
+
+ window.addEventListener('resize', this.positionChangeHandler);
+ window.addEventListener('orientationchange', this.positionChangeHandler);
+ this.menu.element.addEventListener('_closemenu', this.closeMenuHandler);
+
+ this.menu.selected = this.selectedItem;
+ this.menu.open(this.focusElement, position);
+ this.element.setAttribute('aria-expanded', 'true');
+
+ this.focusElementLastScrollPosition = this.focusElement.getBoundingClientRect();
+ }
+ }
+
+ closeMenu(forceFocus = false) {
+ if(this.menu) {
+ this.menu.removeListeners();
+ this.scrollElements.forEach(el => el.removeEventListener('scroll', this.positionChangeHandler));
+ window.removeEventListener('resize', this.positionChangeHandler);
+ window.removeEventListener('orientationchange', this.positionChangeHandler);
+ this.menu.element.removeEventListener('_closemenu', this.closeMenuHandler);
+
+ if (forceFocus) {
+ this.focus();
+ }
+ this.element.setAttribute('aria-expanded', 'false');
+ this.menu.element.setAttribute('hidden', '');
+ }
+ }
+
+ focus() {
+ if(!this.isDisabled()) {
+ this.focusElement.focus();
+ }
+ }
+
+ init() {
+ const addListeners = () => {
+ this.element.addEventListener('keydown', this.keyDownHandler);
+ this.element.addEventListener('click', this.clickHandler);
+ };
+
+ const addWaiAria = () => {
+ this.element.setAttribute('role', 'button');
+ this.element.setAttribute('aria-expanded', 'false');
+ this.element.setAttribute('aria-haspopup', 'true');
+ };
+
+ const addFocusElement = () => {
+ this.focusElement = this.element.querySelector('input[type="text"]');
+ if(!this.focusElement) {
+ this.focusElement = this.element;
+
+ if(!(this.focusElement.tagName.toLowerCase() === 'button' || this.focusElement.tagName.toLowerCase() === 'input')) {
+ if (!this.focusElement.hasAttribute('tabindex')) {
+ this.focusElement.setAttribute('tabindex', '0');
+ }
+ }
+ }
+ };
+
+ const moveElementToDocumentBody = (element) => {
+ // To position an element on top of all other z-indexed elements, the element should be moved to document.body
+ // See: https://philipwalton.com/articles/what-no-one-told-you-about-z-index/
+
+ if(element.parentNode !== document.body) {
+ return document.body.appendChild(element);
+ }
+ return element;
+ };
+
+ const findMenuElement = () => {
+ let menuElement;
+ const menuElementId = this.element.getAttribute('aria-controls');
+ if(menuElementId !== null) {
+ menuElement = document.querySelector(`#${menuElementId }`);
+ }
+ else {
+ menuElement = this.element.parentNode.querySelector(`.${MENU_BUTTON_MENU}`);
+ }
+ return menuElement;
+ };
+
+ const addMenu = () => {
+ const menuElement = findMenuElement();
+ if(menuElement) {
+ if(menuElement.componentInstance) {
+ this.menu = menuElement.componentInstance;
+ }
+ else {
+ this.menu = menuFactory(menuElement);
+ menuElement.componentInstance = this.menu;
+ moveElementToDocumentBody(menuElement);
+ }
+ this.element.setAttribute('aria-controls', this.menu.element.id);
+ }
+ };
+
+ addFocusElement();
+ addWaiAria();
+ addMenu();
+ this.removeListeners();
+ addListeners();
+ }
+
+ downgrade() {
+ if(this.menu) {
+ // Do not downgrade menu if there are other buttons sharing this menu
+ const related = [...document.querySelectorAll(`.${JS_MENU_BUTTON}[aria-controls="${this.element.getAttribute('aria-controls')}"]`)];
+ if(related.filter( c => c !== this.element && c.getAttribute('data-upgraded').indexOf('MaterialExtMenuButton') >= 0).length === 0) {
+ this.menu.downgrade();
+ }
+ }
+ this.removeListeners();
+ }
+
+}
+
+(function() {
+ 'use strict';
+
+ /**
+ * https://github.com/google/material-design-lite/issues/4205
+ * @constructor
+ * @param {Element} element The element that will be upgraded.
+ */
+ const MaterialExtMenuButton = function MaterialExtMenuButton(element) {
+ this.element_ = element;
+ this.menuButton_ = null;
+
+ // Initialize instance.
+ this.init();
+ };
+ window['MaterialExtMenuButton'] = MaterialExtMenuButton;
+
+
+ // Public methods.
+
+ /**
+ * Get the menu element controlled by this button, null if no menu is controlled by this button
+ * @public
+ */
+ MaterialExtMenuButton.prototype.getMenuElement = function() {
+ return this.menuButton_.menu ? this.menuButton_.menu.element : null;
+ };
+ MaterialExtMenuButton.prototype['getMenuElement'] = MaterialExtMenuButton.prototype.getMenuElement;
+
+ /**
+ * Open menu
+ * @public
+ * @param {String} position one of "first", "last" or "selected"
+ */
+ MaterialExtMenuButton.prototype.openMenu = function(position) {
+ this.menuButton_.openMenu(position);
+ };
+ MaterialExtMenuButton.prototype['openMenu'] = MaterialExtMenuButton.prototype.openMenu;
+
+ /**
+ * Close menu
+ * @public
+ */
+ MaterialExtMenuButton.prototype.closeMenu = function() {
+ this.menuButton_.closeMenu(true);
+ };
+ MaterialExtMenuButton.prototype['closeMenu'] = MaterialExtMenuButton.prototype.closeMenu;
+
+ /**
+ * Get selected menu item
+ * @public
+ * @returns {Element} The selected menu item or null if no item selected
+ */
+ MaterialExtMenuButton.prototype.getSelectedMenuItem = function() {
+ return this.menuButton_.selectedItem;
+ };
+ MaterialExtMenuButton.prototype['getSelectedMenuItem'] = MaterialExtMenuButton.prototype.getSelectedMenuItem;
+
+
+ /**
+ * Set (default) selected menu item
+ * @param {Element} item
+ */
+ MaterialExtMenuButton.prototype.setSelectedMenuItem = function(item) {
+ this.menuButton_.selectedItem = item;
+ };
+ MaterialExtMenuButton.prototype['setSelectedMenuItem'] = MaterialExtMenuButton.prototype.setSelectedMenuItem;
+
+ /**
+ * Initialize component
+ */
+ MaterialExtMenuButton.prototype.init = function() {
+ if (this.element_) {
+ this.menuButton_ = new MenuButton(this.element_);
+ this.element_.addEventListener('mdl-componentdowngraded', this.mdlDowngrade_.bind(this));
+ this.element_.classList.add(IS_UPGRADED);
+ }
+ };
+
+ /**
+ * Downgrade component
+ * E.g remove listeners and clean up resources
+ */
+ MaterialExtMenuButton.prototype.mdlDowngrade_ = function() {
+ this.menuButton_.downgrade();
+ };
+
+ // The component registers itself. It can assume componentHandler is available
+ // in the global scope.
+ /* eslint no-undef: 0 */
+ componentHandler.register({
+ constructor: MaterialExtMenuButton,
+ classAsString: 'MaterialExtMenuButton',
+ cssClass: JS_MENU_BUTTON,
+ widget: true
+ });
+})();
diff --git a/node_modules/mdl-ext/src/menu-button/readme.md b/node_modules/mdl-ext/src/menu-button/readme.md
new file mode 100644
index 0000000..ab3a219
--- /dev/null
+++ b/node_modules/mdl-ext/src/menu-button/readme.md
@@ -0,0 +1,472 @@
+# Menu Button
+![Menu button](../../etc/menu-button.png) ![Menu button](../../etc/menu-button-2.png)
+
+A WAI-ARIA friendly menu button component/widget with roles, attributes and behavior in accordance with the specification
+given in WAI-ARIA Authoring Practices, [section 2.20](https://www.w3.org/TR/wai-aria-practices/#button).
+
+## Introduction
+A menu button is a button that opens a menu. It is often styled as a typical push button with a
+downward pointing arrow or triangle to hint that activating the button will display a menu.
+
+A menu is a widget that offers a list of choices to the user, such as a set of actions or functions. A menu is (usually)
+opened, or made visible, by activating a menu button. When a user activates a choice in a menu, the menu (usually) closes.
+
+In this release a `<button>`, an `<input type="text">` or a `<div>` (mdl-textfield) can have `role="button"`, and act as
+the control for a menu.
+
+## To include a MDLEXT **menu button** component:
+
+ 1. Code a `<button>` element; this is the clickable toggle that will show and hide the menu. Include an `aria-controls`
+attribute whose value will match the id attribute of the unordered list coded in the next step. Inside the button,
+code a `<span>` element to hold the button caption text and a `<i>` element to contain a state icon.
+
+```html
+<button aria-controls="menu1">
+ <span></span>
+ <i></i>
+</button>
+```
+
+ 2. Code a `<ul>` unordered list element; this is the container that holds the menu choices. Include an id attribute
+whose value will match the `aria-controls` attribute of the button element.
+
+```html
+<ul id="menu1">
+</ul>
+```
+
+ 3. Inside the unordered list, code one `<li>` element for each choice. Add a text caption as appropriate.
+
+```html
+<ul id="menu1">
+ <li>Small</li>
+ <li>Medium</li>
+ <li>Large</li>
+</ul>
+```
+
+ 4. Add one or more MDL classes, separated by spaces, to the button, span and i elements using the class attribute.
+
+```html
+<button class="mdl-button mdl-js-button" aria-controls="menu1">
+ <span>Select a value</span>
+ <i class="material-icons">more_vert</i>
+</button>
+```
+
+ 5. Add the `mdlext-js-menu-button` class to define the element as a menu button component.
+
+```html
+<button class="mdl-button mdl-js-button mdlext-js-menu-button" aria-controls="menu1">
+ <span>Select a value</span>
+ <i class="material-icons">more_vert</i>
+</button>
+```
+
+ 6. Add the `mdlext-menu` class to the unordered list and the `mdlext-menu__item` class to the list items.
+
+```html
+<ul id="menu1" class="mdlext-menu">
+ <li class="mdlext-menu__item">Small</li>
+ <li class="mdlext-menu__item">Medium</li>
+ <li class="mdlext-menu__item">Large</li>
+</ul>
+```
+
+The menu button component is ready for use.
+
+>**Note:** After page load, the component will add all required Aria roles and attributes.
+
+```html
+<button class="mdl-button mdl-js-button mdlext-js-menu-button"
+ role="button" aria-expanded="false" aria-haspopup="true" aria-controls="menu1">
+ <span>Select a value</span>
+ <i class="material-icons">more_vert</i>
+</button>
+<ul id="menu1" class="mdlext-menu" role="menu" tabindex="-1" hidden>
+ <li class="mdlext-menu__item" role="menuitem" tabindex="-1">Small</li>
+ <li class="mdlext-menu__item" role="menuitem" tabindex="-1">Medium</li>
+ <li class="mdlext-menu__item" role="menuitem" tabindex="-1">Large</li>
+</ul>
+```
+
+
+### Examples
+
+**A menu button with three options.**
+
+```html
+<button class="mdl-button mdl-js-button mdlext-js-menu-button" aria-controls="menu1">
+ <span>Select a value</span>
+ <i class="material-icons">more_vert</i>
+</button>
+<ul id="menu1" class="mdlext-menu">
+ <li class="mdlext-menu__item">Small</li>
+ <li class="mdlext-menu__item">Medium</li>
+ <li class="mdlext-menu__item">Large</li>
+</ul>
+```
+
+> **Note:** If the button and the menu has a common ancestor element, the `aria-controls` attribute of the button and
+the `id` attribute of the menu may be skipped.
+
+```html
+<div role="presentation">
+ <button class="mdl-button mdl-js-button mdlext-js-menu-button">
+ <span>Select a value</span>
+ <i class="material-icons">more_vert</i>
+ </button>
+ <ul class="mdlext-menu">
+ <li class="mdlext-menu__item">Small</li>
+ <li class="mdlext-menu__item">Medium</li>
+ <li class="mdlext-menu__item">Large</li>
+ </ul>
+</div>
+```
+
+With this markup the component will generate a random `id` attribute for the menu and associate it with the `aria-controls`
+of the button.
+
+
+**A menu button with a select listener. Uses a data-value attribute to pass the actual value.**
+
+```html
+<div>
+ <button id="my-button" class="mdl-button mdl-js-button mdl-button--icon mdl-button--primary mdlext-js-menu-button"
+ onmenuselect="document.querySelector('#selection').innerHTML = 'Selected value: ' + event.detail.source.getAttribute('data-value');">
+ <span>Select</span>
+ <i class="mdlext-aria-expanded-more-less"></i>
+ </button>
+ <ul class="mdlext-menu" hidden >
+ <li class="mdlext-menu__item" data-value="10">Ten</li>
+ <li class="mdlext-menu__item" data-value="25">Twentyfive</li>
+ <li class="mdlext-menu__item" data-value="50">Fifty</li>
+ </ul>
+</div>
+```
+```javascript
+document.querySelector('#my-button').addEventListener('menuselect', function(event) {
+ this.querySelector('span').innerHTML = 'Selected value: ' +
+ event.detail.source.getAttribute('data-value')
+});
+```
+
+
+**A menu button decorated with icons**
+
+```html
+<style>
+.material-icons.md-18 {
+ font-size: 18px;
+}
+</style>
+
+<button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button"
+ aria-controls="demo-menu">
+ <i class="material-icons">gesture</i>
+ <span class="mdlext-menu-button__caption">Select</span>
+ <i class="material-icons mdlext-aria-expanded-more-less"></i>
+</button>
+
+<ul id="demo-menu" class="mdlext-menu" hidden>
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">info</i>
+ <span class="mdlext-menu__item__caption">Menu item #1</span>
+ </li>
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">help_outline</i>
+ <span class="mdlext-menu__item__caption">Menu item #2. A long text to check ellipsis overflow 0123456789</span>
+ <i class="material-icons md-18">radio</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item" disabled>
+ <span class="mdlext-menu__item__caption">Menu item #3, disabled</span>
+ <i class="material-icons md-18">accessibility</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #IV</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #V</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VI</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VII</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ Menu item #n
+ </li>
+</ul>
+```
+
+**A mdl-textfield component can be used as a menu button.**
+
+```html
+<style>
+ .mdl-textfield.mdlext-js-menu-button .mdl-textfield__input {
+ padding-right: 40px;
+ }
+ .mdl-textfield__icon {
+ width: 32px;
+ text-align: left;
+ position: absolute;
+ right: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ }
+ .mdl-textfield.is-disabled .mdl-textfield__icon {
+ color: rgba(0, 0, 0, 0.26) !important;
+ }
+ .mdl-textfield.is-invalid .mdl-textfield__icon {
+ color: #de3226 !important;
+ }
+</style>
+
+<div role="presentation">
+ <div id="my-textfield" class="mdl-textfield mdl-js-textfield mdlext-js-menu-button">
+ <input class="mdl-textfield__input" type="text" readonly>
+ <label class="mdl-textfield__label">Sign in with ...</label>
+ <i class="material-icons mdl-textfield__icon mdlext-aria-expanded-more-less"></i>
+ </div>
+ <ul class="mdlext-menu" hidden >
+ <li class="mdlext-menu__item" data-key="S">Small</li>
+ <li class="mdlext-menu__item" data-key="M">Medium</li>
+ <li class="mdlext-menu__item" data-key="L">Large</li>
+ </ul>
+</div>
+```
+```javascript
+document.querySelector('#my-textfield').addEventListener('menuselect', function(event) {
+ this.MaterialTextfield.change(event.detail.source.getAttribute('data-key')
+ + ': ' + event.detail.source.querySelector('span').innerHTML);
+});
+```
+
+**Create your own state icon with SASS.**
+The [_mixins.scss](../_mixins.scss) has a mixin which can be used to create custom state icons.
+
+```sass
+@charset "UTF-8";
+.my-aria-expanded-state {
+ @include mdlext-aria-expanded-toggle($icon: 'arrow_downward', $icon-expanded: 'arrow_upward');
+}
+```
+
+**Use a custom styled `div` as a menu button.**
+
+```html
+<div role="presentation">
+ <div id="my-div" class="mdlext-menu-button mdlext-js-menu-button"
+ style="width:300px; height:44px; max-width:100%; border:1px solid green">
+
+ <span class="mdlext-menu-button__caption">Select a size ...</span>
+ <i class="material-icons my-aria-expanded-state"></i>
+ </div>
+ <ul class="mdlext-menu" hidden >
+ <li class="mdlext-menu__item" data-key="S">Small</li>
+ <li class="mdlext-menu__item" data-key="M">Medium</li>
+ <li class="mdlext-menu__item" data-key="L">Large</li>
+ </ul>
+</div>
+```
+```javascript
+document.querySelector('#my-div').addEventListener('menuselect', function(event) {
+ this.querySelector('span').innerHTML =
+ event.detail.source.getAttribute('data-key') + ': ' +
+ event.detail.source.querySelector('span').innerHTML);
+});
+```
+
+**Many buttons can share one menu.**
+
+```html
+<button class="mdl-button mdl-js-button mdlext-js-menu-button" aria-controls="shared-menu">
+ <span class="mdlext-menu-button__caption">A button</span>
+</button>
+
+<div class="mdl-textfield mdl-js-textfield mdlext-js-menu-button" aria-controls="shared-menu">
+ <input class="mdl-textfield__input" type="text" readonly>
+ <label class="mdl-textfield__label">A MDL textfield</label>
+</div>
+
+<ul id="shared-menu" class="mdlext-menu" hidden>
+ <li class="mdlext-menu__item" role="menuitem">Menu item #1</li>
+ <li class="mdlext-menu__item" role="menuitem">Menu item #2</li>
+ <li class="mdlext-menu__item" role="menuitem">Menu item #n</li>
+</ul>
+```
+
+
+### More examples
+* The [snippets/menu-button.html](./snippets/menu-button.html) and the [tests](../../test/menu-button/menu-button.spec.js) provides more detailed examples.
+* Try out the [live demo](http://leifoolsen.github.io/mdl-ext/demo/menu-button.html)
+
+
+## Characteristics
+
+### Keyboard interaction, Menu Button
+* With focus on the button:
+ * <kbd>Space</kbd> or <kbd>Enter</kbd>: opens the menu, sets `aria-expanded="true"`, and place focus on the previously selected menu item - or on the first menu item if no selected menu item.
+ * <kbd>Down Arrow</kbd>: opens the menu, sets `aria-expanded="true"`, and moves focus to the first menu item.
+ * <kbd>Up Arrow</kbd>: opens the menu, sets `aria-expanded="true"`, and moves focus to the last menu item.
+
+### Mouse interaction, Menu Button
+* With focus on the button:
+ * <kbd>Click</kbd>: opens the menu, sets `aria-expanded="true"`, and place focus on the previously selected menu item - or on the first menu item if no selected menu item.
+ * <kbd>Click</kbd>: a second click closes the menu, sets `aria-expanded="false"` and place focus on button.
+
+### Keyboard interaction, Menu
+* With focus on the menu:
+ * <kbd>Space</kbd> or <kbd>Enter</kbd>: sets `aria-selected="true"` on active menu item, sets `aria-expanded="true"` on menu button, closes menu and moves focus back to menu button. The button emits a custom `select` event with a referfence to the selected menu element.
+ * <kbd>Home</kbd>: move focus to first menu item.
+ * <kbd>End</kbd>: move focus to last menu item.
+ * <kbd>Up Arrow</kbd> or <kbd>Left Arrow</kbd>: move focus to previous menu item.
+ * <kbd>Down Arrow</kbd> or <kbd>Right Arrow</kbd>: Move focus to next menu item.
+ * <kbd>Esc</kbd>: Closes the menu, sets `aria-expanded="true"` on menu button, and move focus back to menu button.
+
+>The keyboard behavior after the menu is open are described in more detail in WAI-ARIA Authoring Practices, [2.19 Menu or Menu bar](https://www.w3.org/TR/wai-aria-practices/#menu).
+
+### Mouse interaction, Menu
+* With focus on the menu:
+ * <kbd>Click</kbd>: sets `aria-selected="true"` on active menu item, sets `aria-expanded="true"` on menu button, closes menu and moves focus back to menu button. The button emits a custom `select` event with a referfence to the selected menu element.
+
+## WAI-ARIA Roles, States, and Properties
+The menu button has the following roles, states and properties set by the menu button component.
+
+### Menu Button
+* `role="button"`: the element that opens the menu has role [button](http://www.w3.org/TR/wai-aria-1.1/#button).
+* `aria-haspopup`: the element with role `button` has [aria-haspopup](http://www.w3.org/TR/wai-aria-1.1/#aria-haspopup) set to `true`.
+* `aria-controls`: identfies the content on the page (e.g. using IDREFs) that this menu button controls.
+* `aria-expanded`: the element with role `button` has [aria-expanded](https://www.w3.org/TR/wai-aria-1.1/#aria-expanded) set to `true` if the corresponding menu is open, oterwise false.
+* `aria-expanded`: when a menu item is disabled, `aria-disabled` is set to `true`.
+* `disabled"`: indicates that a button is disabled, otherwise not present.
+
+### Menu, WAI-ARIA Roles
+* `role="menu"`: identifies the element as a menu widget.
+* `hidden`: the menu has attrubute hidden if the controlling buttoun has `aria-expanded="false"`, otherwise the attribute is not present.
+* `role="menuitem"`: identifies an element as a menu item widget.
+* `role="menuitemcheckbox"`: (not yet implemented).
+* `role="menuitemradion"`: (not yet implemented).
+* `aria-selected`: the selected menu item has `aria-selected="true"`, otherwise not present.
+* `role="separator"`: a divider that separates and distinguishes sections of content or groups of menuitems..
+* `disabled"`: indicates that a menu item is disabled, otherwise not present.
+
+
+>The roles, states, and properties needed for the menu are described in more detail in WAI-ARIA Authoring Practices, [2.19 Menu or Menu bar](https://www.w3.org/TR/wai-aria-practices/#menu).
+
+## Events emitted from the component
+The menu button emits a custom `menuselect` event when a menu item is selected. The event has a detail object with the following structure:
+
+```javascript
+detail: {
+ source: item // The selected menu item
+}
+```
+
+To set up an event listener to receive the select custom event.
+```javascript
+document.querySelector('#my-menubutton').addEventListener('menuselect', function(e) {
+ console.log('menu item selected:', e.detail.source);
+});
+```
+Refer to [snippets/menu-button.html](./snippets/menu-button.html) or the [tests](../../test/menu-button/menu-button.spec.js) for detailed usage.
+
+
+## Public methods
+
+### openMenu(position)
+Open menu at given position. Position is on of `first`, `last` or `selected`. Default value is `first`.
+* `first` focus first menu item
+* `last` focus last menu item
+* `selected` focus previously selected menu item
+
+```javascript
+const menuButton = document.querySelector('#my-menu-button');
+menuButton.MaterialExtMenuButton.openMenu();
+```
+
+### closeMenu()
+Closes an open menu. Moves focus to button.
+
+```javascript
+const menuButton = document.querySelector('#my-menu-button');
+menuButton.MaterialExtMenuButton.closeMenu();
+```
+
+### getMenuElement()
+Get the menu element controlled by this button, null if no menu is controlled by this button.
+
+```javascript
+const menuButton = document.querySelector('#my-menu-button');
+const menu = menuButton.MaterialExtMenuButton.getMenuElement();
+```
+
+### getSelectedMenuItem()
+Get a selected menu item element, null if no menu item element selected.
+
+```javascript
+const menuButton = document.querySelector('#my-menu-button');
+const element = menuButton.MaterialExtMenuButton.getSelectedMenuItem();
+console.log('Selected menu item', element);
+```
+
+### setSelectedMenuItem(item)
+Set a selected menu item element, typically before menu is opened.
+
+```javascript
+const menuButton = document.querySelector('#my-menu-button');
+const menu = menuButton.MaterialExtMenuButton.getMenuElement();
+menuButton.MaterialExtMenuButton.setSelectedMenuItem(menu.children[1]);
+```
+
+Refer to [snippets/menu-button.html](./snippets/menu-button.html) or the [tests](../../test/menu-button/menu-button.spec.js) for detailed usage.
+
+## Configuration options
+
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements to the menu button.
+The table below lists the available classes and their effects.
+
+| MDLEXT class | Effect | Remarks |
+|----------------------------------|--------|---------|
+|`mdlext-menu-button` | Basic styling for a menu button | Optional on a div element |
+|`mdlext-js-menu-button` | Assigns basic MDLEXT behavior to menu button. Identifies the element as a menu button component | Required on the element that should act as a menu button |
+|`mdlext-menu-button__caption` | Holds the button text | Optional on span element inside menu button element - but required if you want to decorate a button with icons. More than one caption can be used to control various aspects of the button text, e.g. font size. |
+|`material-icons` | Defines span as a material icon | Required on an inline element. Decorates button or menu item with an icon |
+|`mdlext-menu` | Defines an unordered list container as an MDLEXT component | Required on ul element |
+|`mdlext-menu__item` | Defines menu options | Required on list item elements |
+|`mdlext-menu__item__caption` | Holds the menu text | Optional on span element inside list item element - but required if you want to decorate a menu item with icons. More than one caption can be used to control various aspects of the menu text, e.g. font size. |
+|`mdlext-menu__item-separator` | Items in a menu may be divided into groups by placing an element with a role of `separator` between groups. | Optional; goes on unordered list element |
+|`mdlext-aria-expanded-plus-minus` | State icon. Displays '+' or '-' | Optional; goes on button element |
+|`mdlext-aria-expanded-more-less` | State icon. Displays 'more' or 'less' Material Design icons | Optional; goes on button element |
+
+> **Note:**
+> Disabled versions of the menu items are provided, and are invoked with the standard HTML boolean attribute `disabled`
+`<li class="mdlext-menu__item" disabled>A menu item</li>`. This attribute may be added or removed programmatically via scripting.
+
+> If you decorate the menu button with icons, wrap the button text inside a span to separate icons and text
+```html
+<button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+ <i class="material-icons">gesture</i>
+ <span class="mdlext-menu-button__caption">Select</span>
+ <i class="material-icons mdlext-menu-button__aria-expanded-more-less"></i>
+</button>
+```
+
+> If you decorate a menu item with icons, wrap the menu item text inside a span to separate icons and text
+```html
+<ul id="demo-menu" class="mdlext-menu" hidden>
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">help_outline</i>
+ <span class="mdlext-menu__item__caption">Menu item</span>
+ <i class="material-icons">info</i>
+ </li>
+</ul>
+```
diff --git a/node_modules/mdl-ext/src/menu-button/snippets/menu-button.html b/node_modules/mdl-ext/src/menu-button/snippets/menu-button.html
new file mode 100644
index 0000000..784f280
--- /dev/null
+++ b/node_modules/mdl-ext/src/menu-button/snippets/menu-button.html
@@ -0,0 +1,594 @@
+<article>
+<p>A menu button is a button that opens a menu. It is often styled as a typical push button with a
+downward pointing arrow or triangle to hint that activating the button will display a menu.
+The menu button has roles, attributes and behaviour as outlined in
+<a href="https://www.w3.org/TR/wai-aria-practices/#menubutton" target="_blank">WAI-ARIA Authoring Practices</a>.
+</p>
+</article>
+
+<link rel="stylesheet" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
+
+<style>
+ .size-22 {
+ font-size: 22px;
+ width: 22px;
+ text-align: center;
+ vertical-align: middle;
+ }
+
+ .mdl-cell p {
+ margin-bottom: 0;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+
+
+ .mdl-textfield.mdlext-js-menu-button .mdl-textfield__input {
+ padding-right: 40px;
+ }
+
+ .mdl-textfield__icon {
+ width: 32px;
+ text-align: left;
+ position: absolute;
+ right: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ }
+
+ .mdl-textfield.is-disabled .mdl-textfield__icon {
+ color: rgba(0, 0, 0, 0.26) !important;
+ }
+
+ .mdl-textfield.is-invalid .mdl-textfield__icon {
+ color: #de3226 !important;
+ }
+
+ #max-width-menu {
+ max-width: 400px;
+ }
+
+</style>
+
+<script>
+ function signedIn(sn) {
+ return 'Signed in with <i class="size-22 icon ion-social-' + sn + '"></i> ';
+ }
+ function signedInIcon(sn) {
+ return '<i class="size-22 icon ion-social-' + sn + '"></i>';
+ }
+</script>
+
+<div class="mdl-grid mdl-grid--no-spacing">
+ <div class="mdl-cell mdl-cell--4-col">
+ <p><code>mdl-button</code></p>
+ <button id="btn-social-1" style="width:100%; max-width:300px; height:46px"
+ class="mdl-button mdl-button--colored mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button"
+ aria-controls="shared-social-menu" >
+ <i class="material-icons">person_outline</i>
+ <span class="mdlext-menu-button__caption">Sign in with ...</span>
+ <i class="material-icons mdlext-aria-expanded-more-less"></i>
+ </button>
+ <script>
+ document.querySelector('#btn-social-1').addEventListener('menuselect', function(event) {
+ this.querySelector('.mdlext-menu-button__caption').innerHTML = signedIn(event.detail.source.getAttribute('data-value'));
+ });
+ </script>
+ </div> <!--cell -->
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p><code>mdl-textfield</code></p>
+ <div id="btn-social-2"
+ class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-js-menu-button"
+ aria-controls="shared-social-menu">
+ <input class="mdl-textfield__input" type="text" readonly>
+ <label class="mdl-textfield__label">Sign in with ...</label>
+ <i class="material-icons mdl-textfield__icon mdlext-aria-expanded-more-less"></i>
+ </div>
+ <script>
+ document.querySelector('#btn-social-2').addEventListener('menuselect', function(event) {
+ this.MaterialTextfield.change(event.detail.source.querySelector('span').innerHTML);
+ });
+ </script>
+ </div> <!--cell -->
+
+ <div class="mdl-cell mdl-cell--4-col mdlext-bordered-fields">
+ <p><code>mdlext-bordered-fields</code></p>
+ <div id="btn-social-3"
+ class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right mdlext-js-menu-button"
+ aria-controls="shared-social-menu">
+ <input class="mdl-textfield__input" type="text" readonly>
+ <label class="mdl-textfield__label">Sign in with ...</label>
+ <i class="material-icons mdlext-aria-expanded-more-less"></i>
+ </div>
+ <script>
+ document.querySelector('#btn-social-3').addEventListener('menuselect', function(event) {
+ this.MaterialTextfield.change(event.detail.source.querySelector('span').innerHTML);
+ });
+ </script>
+ </div> <!--cell -->
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>custom styled <code><div></code></p>
+ <div id="btn-social-4"
+ class="mdlext-menu-button mdlext-js-menu-button" style="width:300px; height:46px; max-width:100%; border:1px solid green"
+ aria-controls="shared-social-menu">
+ <span class="mdlext-menu-button__caption">Sign in with ...</span>
+ <i class="material-icons mdlext-aria-expanded-more-less"></i>
+ </div>
+ <script>
+ document.querySelector('#btn-social-4').addEventListener('menuselect', function(event) {
+ this.querySelector('span').innerHTML = signedIn(event.detail.source.getAttribute('data-value')) + ', ' +
+ event.detail.source.querySelector('span').innerHTML;
+ });
+ </script>
+ </div> <!--cell -->
+
+
+ <div class="mdl-cell mdl-cell--4-col">
+ <p>mdl-button--icon</p>
+
+ <button id="btn-social-5" style="height:46px; width:46px;"
+ class="mdl-button mdl-js-button mdl-button--icon mdlext-js-menu-button"
+ aria-controls="shared-social-menu">
+ <i class="material-icons">more_vert</i>
+ </button>
+ <script>
+ document.querySelector('#btn-social-5').addEventListener('menuselect', function(event) {
+ this.innerHTML = signedInIcon(event.detail.source.getAttribute('data-value'));
+ });
+ </script>
+
+ </div> <!--cell -->
+
+</div> <!-- grid -->
+
+<ul id="shared-social-menu" class="mdlext-menu" hidden >
+ <li class="mdlext-menu__item" data-value="twitter">
+ <span class="mdlext-menu__item__caption">Twitter</span>
+ <i class="icon ion-social-twitter-outline size-22"></i>
+ </li>
+ <li class="mdlext-menu__item" data-value="github">
+ <span class="mdlext-menu__item__caption">GitHub</span>
+ <i class="ion-social-github-outline size-22"></i>
+ </li>
+ <li class="mdlext-menu__item" data-value="googleplus">
+ <span class="mdlext-menu__item__caption">G+</span>
+ <i class="ion-social-googleplus-outline size-22"></i>
+ </li>
+ <li class="mdlext-menu__item" data-value="linkedin">
+ <span class="mdlext-menu__item__caption">LinkedIn</span>
+ <i class="icon ion-social-linkedin-outline size-22"></i>
+ </li>
+ <li class="mdlext-menu__item" data-value="facebook">
+ <span class="mdlext-menu__item__caption">Facebook</span>
+ <i class="icon ion-social-facebook-outline size-22"></i>
+ </li>
+</ul>
+
+<p style="margin-top: 16px;">Menu buttons positioned left, middle and right, using <code>textalign</code>.</p>
+<div role="presentation">
+ <button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+ <i class="material-icons">gesture</i>
+ <span class="mdlext-menu-button__caption">Select</span>
+ <i class="material-icons mdlext-aria-expanded-more-less"></i>
+ </button>
+ <ul id="max-width-menu" class="mdlext-menu" hidden >
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">info</i>
+ <span class="mdlext-menu__item__caption">Menu item #1</span>
+ </li>
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">help_outline</i>
+ <span class="mdlext-menu__item__caption">Menu item #2. A long text to check ellipsis overflow 0123456789</span>
+ <i class="material-icons md-18">radio</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item" disabled>
+ <span class="mdlext-menu__item__caption">Menu item #3, disabled</span>
+ <i class="material-icons md-18">accessibility</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #IV</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #V</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VI</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VII</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ Menu item #n
+ </li>
+ </ul>
+</div>
+
+
+<div role="presentation" style="text-align: center">
+ <button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+ <i class="material-icons">gesture</i>
+ <span class="mdlext-menu-button__caption">Select</span>
+ <i class="material-icons mdlext-aria-expanded-more-less"></i>
+ </button>
+ <ul class="mdlext-menu" hidden >
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">info</i>
+ <span class="mdlext-menu__item__caption">Menu item #1</span>
+ </li>
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">help_outline</i>
+ <span class="mdlext-menu__item__caption">Menu item #2</span>
+ <i class="material-icons md-18">radio</i>
+ </li>
+ <li class="mdlext-menu__item" disabled>
+ <span class="mdlext-menu__item__caption">Menu item #3, disabled</span>
+ <i class="material-icons md-18">accessibility</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #IV</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #V</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VI</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VII</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VIII</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #IX</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #X</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #XI</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #XII</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #XIII</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #XIV</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #XV</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #XVI</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #XVII</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #XVIII</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #XIX</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #XX</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ Menu item #n
+ </li>
+ </ul>
+</div>
+
+
+<div role="presentation" style="text-align: right">
+ <button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+ <i class="material-icons">gesture</i>
+ <span class="mdlext-menu-button__caption">Select</span>
+ <i class="material-icons mdlext-aria-expanded-more-less"></i>
+ </button>
+ <ul class="mdlext-menu" hidden >
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">info</i>
+ <span class="mdlext-menu__item__caption">Menu item #1</span>
+ </li>
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">help_outline</i>
+ <span class="mdlext-menu__item__caption">Menu item #2</span>
+ <i class="material-icons md-18">radio</i>
+ </li>
+ <li class="mdlext-menu__item" disabled>
+ <span class="mdlext-menu__item__caption">Menu item #3, disabled</span>
+ <i class="material-icons md-18">accessibility</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #IV</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #V</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VI</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VII</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ Menu item #n
+ </li>
+ </ul>
+</div>
+
+
+<p style="margin-top: 16px">This menu button has WAIA roles and attributes coded in markup</p>
+<button id="aria-demo-button"
+ class="mdl-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button"
+ role="button"
+ aria-haspopup="true"
+ aria-controls="menu-example-dropdown"
+ aria-expanded="false"
+ tabindex="0">
+ <span class="mdlext-menu-button__caption">Select a size</span>
+ <i class="mdlext-aria-expanded-plus-minus"></i>
+</button>
+<script>
+ document.querySelector('#aria-demo-button').addEventListener('menuselect', function(event) {
+ this.querySelector('span').innerHTML = 'Size: ' + event.detail.source.innerHTML;
+ });
+</script>
+<ul id="menu-example-dropdown"
+ class="mdlext-menu"
+ role="menu"
+ hidden >
+ <li class="mdlext-menu__item" role="menuitem">X Small</li>
+ <li class="mdlext-menu__item-separator" role="separator"></li>
+ <li class="mdlext-menu__item" role="menuitem">Small</li>
+ <li class="mdlext-menu__item" role="menuitem">Medium</li>
+ <li class="mdlext-menu__item" role="menuitem">Large</li>
+ <li class="mdlext-menu__item-separator" role="separator"></li>
+ <li class="mdlext-menu__item" role="menuitem">X Large</li>
+ <li class="mdlext-menu__item" role="menuitem">XXX Large</li>
+</ul>
+
+<p style="margin-top: 16px">A disabled menu button should do nothing</p>
+<div role="presentation">
+ <button class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdlext-js-menu-button" disabled>
+ <span class="mdlext-menu-button__caption">Disabled</span>
+ <i class="material-icons mdlext-aria-expanded-more-less"></i>
+ </button>
+ <ul class="mdlext-menu" hidden>
+ <li class="mdlext-menu__item">Menu item #1</li>
+ </ul>
+</div>
+
+
+<p style="margin-top: 16px">Menu buttons inside a table. Menus placed inside and after the table element to verify
+ that positioning works as expected.</p>
+
+<div style="position:relative; border:2px solid green; overflow: hidden;">
+<p>The box with green borders has <code>overflow:hidden</code></p>
+<div>
+
+ <table id="a-table-with-menu-buttons"
+ class="mdl-data-table mdl-js-data-table mdl-data-table--selectable mdl-shadow--2dp" style="width: 48%; float:left;">
+ <thead>
+ <tr>
+ <th class="mdl-data-table__cell--non-numeric">Material</th>
+ <th>Quantity</th>
+ <th>Unit price</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td class="mdl-data-table__cell--non-numeric">Acrylic (Transparent)</td>
+ <td>
+ <span style="width:40px; display: inline-block;"></span>
+ <button class="mdl-button mdl-js-button mdl-button--icon mdl-button--primary mdlext-js-menu-button"
+ aria-controls="table-menu-example">
+ <i class="mdlext-aria-expanded-more-less"></i>
+ </button>
+ </td>
+ <td>$2.90</td>
+ </tr>
+ <tr>
+ <td class="mdl-data-table__cell--non-numeric">Plywood (Birch)</td>
+ <td>
+ <span style="width:40px; display: inline-block;"></span>
+ <button class="mdl-button mdl-js-button mdl-button--icon mdl-button--primary mdlext-js-menu-button"
+ aria-controls="table-menu-example">
+ <i class="mdlext-aria-expanded-more-less"></i>
+ </button>
+ </td>
+ <td>$1.25</td>
+ </tr>
+ <tr>
+ <td class="mdl-data-table__cell--non-numeric">Laminate (Gold on Blue)</td>
+ <td>
+ <span style="width:40px; display: inline-block;"></span>
+ <button class="mdl-button mdl-button--icon mdl-button--primary mdl-js-button mdlext-js-menu-button"
+ aria-controls="table-menu-example">
+ <i class="mdlext-aria-expanded-more-less"></i>
+ </button>
+ </td>
+ <td>$2.35</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <script>
+ document.querySelector('#a-table-with-menu-buttons').addEventListener('menuselect', function(event) {
+ var span = event.target.closest('td').querySelector('span');
+ span.innerHTML = event.detail.source.getAttribute('data-value');
+ });
+ </script>
+
+ <div role="presentation" style="width:48%; float:right;">
+ <p style="margin-top: 16px">This menu button has a menu with dark color theme, <code>mdlext-dark-color-theme</code> class</p>
+
+ <button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+ <i class="material-icons">gesture</i>
+ <span class="mdlext-menu-button__caption">Select</span>
+ <i class="material-icons mdlext-aria-expanded-more-less"></i>
+ </button>
+ <ul class="mdlext-menu mdlext-dark-color-theme" hidden >
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">info</i>
+ <span class="mdlext-menu__item__caption">Menu item #1</span>
+ </li>
+ <li class="mdlext-menu__item">
+ <i class="material-icons md-18">help_outline</i>
+ <span class="mdlext-menu__item__caption">Menu item #2. A long text to check ellipsis overflow 0123456789</span>
+ <i class="material-icons md-18">radio</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item" disabled>
+ <span class="mdlext-menu__item__caption">Menu item #3, disabled</span>
+ <i class="material-icons md-18">accessibility</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #IV</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #V</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ <li class="mdlext-menu__item-separator"></li>
+ <li class="mdlext-menu__item">
+ <span class="mdlext-menu__item__caption">Menu item #VI</span>
+ <i class="material-icons md-18">build</i>
+ </li>
+ </ul>
+ </div>
+
+</div>
+</div>
+
+<ul id="table-menu-example" class="mdlext-menu" hidden >
+ <li class="mdlext-menu__item" data-value="10">Ten</li>
+ <li class="mdlext-menu__item" data-value="25">Twentyfive</li>
+ <li class="mdlext-menu__item" data-value="50">Fifty</li>
+</ul>
+
+
+<style>
+ .demo-grid {
+ margin-top: 32px;
+ }
+ .demo-grid .mdl-cell {
+ background: rgb(63,81,181);
+ text-align: center;
+ color: white;
+ padding: 16px 8px;
+ border: 1px solid #aaaaaa;
+ }
+ .demo-grid .mdl-cell:nth-child(odd) {
+ background: rgb(33,150,243);
+ }
+</style>
+
+
+<div id="a-grid-with-menu-buttons" class="demo-grid">
+ <p>Menu buttons inside <code>mdl-grid</code></p>
+
+ <div id="menu-button-grid" class="mdl-grid mdl-grid--no-spacing">
+ <div class="mdl-cell mdl-cell--4-col mdl-cell--4-col-tablet mdl-cell--2-col-phone">
+ <button class="mdl-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+ <span class="mdlext-menu-button__caption">Select a size</span>
+ <i class="mdlext-aria-expanded-plus-minus"></i>
+ </button>
+ <ul class="mdlext-menu"
+ role="menu"
+ hidden >
+ <li class="mdlext-menu__item" role="menuitem">Small</li>
+ <li class="mdlext-menu__item" role="menuitem">Medium</li>
+ <li class="mdlext-menu__item" role="menuitem">Large</li>
+ </ul>
+ </div>
+ <div class="mdl-cell mdl-cell--5-col mdl-cell--4-col-tablet mdl-cell--2-col-phone">
+ <button class="mdl-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+ <span class="mdlext-menu-button__caption">Select a size</span>
+ <i class="mdlext-aria-expanded-plus-minus"></i>
+ </button>
+ <ul class="mdlext-menu"
+ role="menu"
+ hidden >
+ <li class="mdlext-menu__item" role="menuitem">Small</li>
+ <li class="mdlext-menu__item" role="menuitem">Medium</li>
+ <li class="mdlext-menu__item" role="menuitem">Large</li>
+ </ul>
+ </div>
+ <div class="mdl-cell mdl-cell--3-col mdl-cell--4-col-tablet mdl-cell--hide-phone">
+ <button class="mdl-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+ <span class="mdlext-menu-button__caption">Select a size</span>
+ <i class="mdlext-aria-expanded-plus-minus"></i>
+ </button>
+ <ul class="mdlext-menu"
+ role="menu"
+ hidden >
+ <li class="mdlext-menu__item" role="menuitem">Small</li>
+ <li class="mdlext-menu__item" role="menuitem">Medium</li>
+ <li class="mdlext-menu__item" role="menuitem">Large</li>
+ </ul>
+ </div>
+ </div>
+</div>
+<script>
+ document.querySelector('#a-grid-with-menu-buttons').addEventListener('menuselect', function(event) {
+ event.target.querySelector('span').innerHTML = 'Size: ' + event.detail.source.innerHTML;
+ });
+</script>
+
+<div style="margin-bottom:256px;"></div>
+
+<!--
+https://www.w3.org/TR/wai-aria-practices/#menubutton
+http://w3c.github.io/aria-practices/examples/menu-button/menu-button-1.html
+http://w3c.github.io/aria-practices/examples/menu-button/menu-button-2.html
+http://tympanus.net/codrops/2012/10/04/custom-drop-down-list-styling/
+http://www.slideshare.net/webaxe/html5-dev-con-2012-aria-widget
+http://terrillthompson.com/blog/474
+https://github.com/davidtheclark/react-aria-menubutton
+https://codepen.io/tiffanytse/pen/Dkvtr
+https://codepen.io/andytran/pen/vLNGvN
+https://codepen.io/dapacreative/pen/WQoLzb
+https://codepen.io/gabrieltomescu/pen/ZGGyPK
+https://codepen.io/Idered/pen/vowrB
+https://codepen.io/Stedesign/pen/DbAJh
+http://markbirbeck.com/2015/10/14/a-mixin-approach-to-material-design-lite-using-sass/
+-->
diff --git a/node_modules/mdl-ext/src/selectfield/_selectfield.scss b/node_modules/mdl-ext/src/selectfield/_selectfield.scss
new file mode 100644
index 0000000..cd4ecfc
--- /dev/null
+++ b/node_modules/mdl-ext/src/selectfield/_selectfield.scss
@@ -0,0 +1,273 @@
+/**
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Copied/Modified/Inspired from/by:
+ * https://github.com/google/material-design-lite/tree/master/src/textfield
+ * http://red-team-design.com/making-html-dropdowns-not-suck/
+ * http://codepen.io/etcpe9/pen/PqyOye,
+ * http://codepen.io/pudgereyem/pen/PqBxQx
+ * https://github.com/MEYVN-digital/mdl-selectfield
+ * https://github.com/mebibou/mdl-selectfield
+ */
+
+// Use of this module requires the user to include variables from material-design-lite
+//@import "../../node_modules/material-design-lite/src/variables";
+//@import "../../node_modules/material-design-lite/src/mixins";
+
+@import "../mixins";
+
+// The container for the selectfield.
+.mdlext-selectfield {
+ box-sizing: border-box;
+ position: relative;
+ font-size: $input-text-font-size;
+ display: inline-block;
+ width: 300px;
+ max-width: 100%;
+ margin: 0;
+ padding: $input-text-vertical-spacing 0;
+
+ // Align buttons, if used.
+ & .mdl-button {
+ bottom: $input-text-vertical-spacing;
+ position: absolute;
+ }
+
+ // Styling the down arrow
+ &::after {
+ @include mdlext-arrow(bottom, $mdlext-selectfield-arrow-width, $mdlext-selectfield-arrow-length);
+
+ position: absolute;
+ right: 0.5em;
+ top: 50%;
+ transform: translateY(-50%);
+ pointer-events: none;
+ }
+}
+
+.mdlext-selectfield.is-disabled {
+ &::after {
+ color: $input-text-disabled-color;
+ @include mdlext-arrow(bottom, $mdlext-selectfield-arrow-width, $mdlext-selectfield-arrow-length, $input-text-disabled-color);
+ }
+}
+
+// Optional class to align right.
+.mdlext-selectfield--align-right {
+ text-align: right;
+}
+
+// Optional class to display at full width.
+.mdlext-selectfield--full-width {
+ width: 100%;
+}
+
+// Optional class to make the select field expandable.
+.mdlext-selectfield--expandable {
+ min-height: $input-text-button-size;
+ min-width: $input-text-button-size;
+ width: auto;
+}
+
+// Styling for the select element.
+.mdlext-selectfield__select {
+
+ // Reset select
+ box-sizing: border-box;
+ border: 0;
+ border-radius: 0;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ -ms-appearance: none;
+ appearance: none;
+ text-indent: 0.01px; // Removes default arrow from firefox
+ text-overflow: ''; // Removes default arrow from firefox
+ outline: none;
+ box-shadow: none;
+ // End Reset select
+
+ font-size: $input-text-font-size;
+ font-family: $performance_font;
+ padding: $input-text-padding calc(1.2em + #{$input-text-padding}) $input-text-padding 0;
+ width: $input-text-width;
+ border-bottom: 1px solid $input-text-bottom-border-color;
+ display: block;
+ margin: 0;
+ background: none;
+ text-align: left;
+ color: inherit;
+
+ // Mozilla, remove focusring
+ &:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 #000000;
+ }
+
+ // MS, remove selected option background color
+ &:focus::-ms-value {
+ background-color: inherit;
+ color: inherit;
+ }
+
+ &::-ms-expand {
+ display: none;
+ }
+
+ .mdlext-selectfield.is-focused & {
+ outline: none;
+ }
+
+ .mdlext-selectfield.is-invalid & {
+ border-color: $input-text-error-color;
+ box-shadow: none;
+ }
+
+ fieldset[disabled] .mdlext-selectfield &,
+ .mdlext-selectfield.is-disabled & {
+ border-bottom: 1px dotted $input-text-disabled-color;
+ color: $input-text-disabled-text-color;
+ background-color: transparent;
+ }
+
+ option {
+ color: $text-color-primary;
+ box-sizing: border-box;
+ background-color: inherit;
+ }
+}
+
+// Styling for the label / floating label.
+.mdlext-selectfield__label {
+ box-sizing: border-box;
+ color: $input-text-label-color;
+ font-size: $input-text-font-size;
+ top: ($input-text-padding + $input-text-vertical-spacing);
+ bottom: 0;
+ left: 0;
+ right: 0;
+ pointer-events: none;
+ position: absolute;
+ display: block;
+ width: 100%;
+ overflow: hidden;
+ white-space: nowrap;
+ text-align: left;
+
+ .mdlext-selectfield.is-dirty &,
+ .mdlext-selectfield.has-placeholder & {
+ visibility: hidden;
+ }
+
+ // Floating Label
+ .mdlext-selectfield--floating-label & {
+ @include material-animation-default();
+ }
+
+ .mdlext-selectfield--floating-label.has-placeholder & {
+ transition: none;
+ }
+
+ fieldset[disabled] .mdlext-selectfield &,
+ .mdlext-selectfield.is-disabled.is-disabled & {
+ color: $input-text-disabled-text-color;
+ }
+
+ .mdlext-selectfield--floating-label.is-focused &,
+ .mdlext-selectfield--floating-label.is-dirty.is-dirty &,
+ .mdlext-selectfield--floating-label.has-placeholder & {
+ color: $input-text-highlight-color;
+ font-size: $input-text-floating-label-fontsize;
+ top: $input-text-vertical-spacing - ($input-text-floating-label-fontsize + $input-text-padding);
+ visibility: visible;
+ }
+
+ .mdlext-selectfield--floating-label.is-focused .mdlext-selectfield__expandable-holder &,
+ .mdlext-selectfield--floating-label.is-dirty .mdlext-selectfield__expandable-holder &,
+ .mdlext-selectfield--floating-label.has-placeholder .mdlext-selectfield__expandable-holder & {
+ top: -($input-text-floating-label-fontsize + $input-text-padding);
+ }
+
+ .mdlext-selectfield--floating-label.is-invalid & {
+ color: $input-text-error-color;
+ font-size: $input-text-floating-label-fontsize;
+ }
+
+ // The after label is the colored underline for the Selectfield.
+ &::after {
+ background-color: $input-text-highlight-color;
+ bottom: $input-text-vertical-spacing;
+ content: '';
+ height: 2px;
+ left: 45%;
+ position: absolute;
+ @include material-animation-default();
+
+ visibility: hidden;
+ width: 10px;
+ }
+
+ .mdlext-selectfield.is-focused &::after {
+ left: 0;
+ visibility: visible;
+ width: 100%;
+ }
+
+ .mdlext-selectfield.is-invalid &::after {
+ background-color: $input-text-error-color;
+ }
+}
+
+// SelectField Error.
+.mdlext-selectfield__error {
+ color: $input-text-error-color;
+ font-size: $input-text-floating-label-fontsize;
+ position: absolute;
+ margin-top: 3px;
+ visibility: hidden;
+ display: block;
+
+ .mdlext-selectfield.is-invalid & {
+ visibility: visible;
+ }
+}
+
+// Expandable Holder.
+.mdlext-selectfield__expandable-holder {
+ display: inline-block;
+ position: relative;
+ margin-left: $input-text-button-size;
+
+ @include material-animation-default();
+
+ // Safari (possibly others) need to be convinced that this field is actually
+ // visible, otherwise it cannot be tabbed to nor focused via a <label>.
+ // TODO: In some cases (Retina displays), this is big enough to render the
+ // inner element :(
+ max-width: 0.1px;
+
+ .mdlext-selectfield.is-focused &,
+ .mdlext-selectfield.is-dirty & {
+ // This is an unfortunate hack. Animating between widths in percent (%)
+ // in many browsers (Chrome, Firefox) only animates the inner visual style
+ // of the input - the outer bounding box still 'jumps'.
+ // Thus assume a sensible maximum, and animate to/from that value.
+ max-width: 600px;
+ }
+ .mdlext-selectfield__label::after {
+ bottom: 0;
+ }
+}
diff --git a/node_modules/mdl-ext/src/selectfield/readme.md b/node_modules/mdl-ext/src/selectfield/readme.md
new file mode 100644
index 0000000..891ea36
--- /dev/null
+++ b/node_modules/mdl-ext/src/selectfield/readme.md
@@ -0,0 +1,152 @@
+# Selectfield
+![Selectfield](../../etc/select-element.png)
+
+## Introduction
+The [HTML select](https://developer.mozilla.org/en/docs/Web/HTML/Element/select) (`<select>`) element represents
+a control that presents a menu of options. The options within the menu are represented by `<option>` elements,
+which can be grouped by `<optgroup>` elements. Options can be pre-selected for the user.
+
+The Material Design Lite Ext (MDLEXT) **select field** component is an enhanced version of the standard
+[HTML `<select>`] (https://developer.mozilla.org/en/docs/Web/HTML/Element/select) element.
+A select field consists of a horizontal line indicating where keyboard input can occur and, typically, text that clearly communicates
+the intended contents of the select field. An icon (at the right hand side) indicates that the select field has user selectable options.
+
+This component relates to the guidelines given in [Materials Design spesifications page, Text Fields](http://www.google.com/design/spec/components/text-fields.html).
+
+### To include a MDLEXT **select field** component:
+
+ 1. Code a `<div>` element to hold the select field.
+```html
+<div>
+...
+</div>
+```
+
+ 2. Inside the div, code an `<select>` element with an `id` attribute of your choice.
+```html
+<div>
+ <select id="some-id">
+ </select>
+</div>
+```
+
+ 3. Inside the `<select>` element code a list of user selectable options.
+```html
+<div>
+ <select id="some-id">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ </select>
+</div>
+```
+
+ 4. Also inside the div, after the `<select>` element, code a `<label>` element with a `for` attribute
+whose value matches the `select` element's `id` value, and a short string to be used as the field's placeholder text.
+```html
+<div>
+ <select id="some-id">
+ ...
+ </select>
+ <label for="some-id">Options</label>
+</div>
+```
+
+ 5. Add one or more MDLEXT classes, separated by spaces, to the select field container,
+select element, label element, and error message using the `class` attribute.
+```html
+<div class="mdlext-selectfield mdlext-js-selectfield">
+ <select id="some-id" class="mdlext-selectfield__select">
+ ...
+ </select>
+ <label for="some-id" class="mdlext-selectfield__label">Options</label>
+ <span class="mdlext-selectfield__error">Someting is wrong</span>
+</div>
+```
+The select field component is ready for use.
+
+#### Examples
+
+Select field with a standard label.
+```html
+<div class="mdlext-selectfield mdlext-js-selectfield">
+ <select id="some-id" class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ </select>
+ <label for="some-id" class="mdlext-selectfield__label">Options</label>
+</div>
+```
+
+Select field with a floating label.
+```html
+<div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select id="some-id" class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ </select>
+ <label for="some-id" class="mdlext-selectfield__label">Options</label>
+</div>
+```
+
+Select field with a standard label and error message.
+```html
+<div class="mdlext-selectfield mdlext-js-selectfield">
+ <select id="some-id" class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ </select>
+ <label for="some-id" class="mdlext-selectfield__label">Options</label>
+ <span class="mdlext-selectfield__error">Something is wrong</span>
+</div>
+```
+
+
+## Configuration options
+
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements to the select field.
+The table below lists the available classes and their effects.
+
+| MDLEXT class | Effect | Remarks |
+|-----------|--------|---------|
+| `mdlext-selectfield` | Defines container as an MDL component | Required on "outer" div element|
+| `mdlext-js-selectfield` | Assigns basic MDL behavior to input | Required on "outer" div element |
+| `mdlext-selectfield__select` | Defines element as selectfield select | Required on select element |
+| `mdlext-selectfield__label` | Defines element as selectfield label | Required on label element for select elements |
+| `mdlext-selectfield--floating-label` | Applies *floating label* effect | Optional; goes on "outer" div element |
+| `mdlext-selectfield__error` | Defines span as an MDL error message | Optional; goes on span element for MDL select element with *pattern*|
+| `is-invalid` | Defines the selectfield as invalid on initial load. | Optional on `mdlext-selectfield` element |
+<!--
+| `mdlext-selectfield--expandable` | Defines a div as an MDL expandable select field container | For expandable select fields, required on "outer" div element |
+| `mdl-button` | Defines label as an MDL icon button | For expandable select fields, required on "outer" div's label element |
+| `mdl-js-button` | Assigns basic behavior to icon container | For expandable input fields, required on "outer" div's label element |
+| `mdl-button--icon` | Defines label as an MDL icon container | For expandable select fields, required on "outer" div's label element |
+| `mdl-input__expandable-holder` | Defines a container as an MDL component | For expandable select fields, required on "inner" div element |
+-->
+
+>**Note I:** Disabled versions of each select field type are provided, and are invoked with the standard HTML boolean attribute `disabled`. `<select class="mdlext-selectfield__select" id="select-id" name="select-id" disabled>`
+>This attribute may be added or removed programmatically via scripting.
+
+>**Note II:** The select field can for some browser and OS combinations, e.g.
+>FireFox and OSX, be off by 2 pixels compared to the input field. There is no
+>way to fix this, as far as I know, without setting an explicit height on both field types.
+>Since MDL does not set a specific height of the text field, it can not be done for the select
+>field either. If alignment is required, the user must in his/hers design set a specific height
+>both for textfields and selectfields.
+
+## How to use the component programmatically
+The tests provides examples on how to use the component [programmatically](https://github.com/leifoolsen/mdl-ext/blob/master/test/selectfield/selectfield.spec.js)
+
+### Credits
+The Select component is based on the following sources:
+* [Material Design Lite selectfield component](https://github.com/mebibou/mdl-selectfield)
+* [mdl-selectfield](https://github.com/MEYVN-digital/mdl-selectfield)
+* [Simple Material Design Login, with select field](http://codepen.io/michaelschofield/pen/qEzWaM)
+* [Material Design <select> element, css only](http://codepen.io/pudgereyem/pen/PqBxQx)
diff --git a/node_modules/mdl-ext/src/selectfield/selectfield.js b/node_modules/mdl-ext/src/selectfield/selectfield.js
new file mode 100644
index 0000000..459f0b8
--- /dev/null
+++ b/node_modules/mdl-ext/src/selectfield/selectfield.js
@@ -0,0 +1,277 @@
+/**
+ * @license
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+/*
+ * Copied/Modified from https://github.com/google/material-design-lite/tree/master/src/textfield
+ */
+
+import { randomString } from '../utils/string-utils';
+import {
+ IS_DIRTY,
+ IS_FOCUSED,
+ IS_DISABLED,
+ IS_INVALID,
+ IS_UPGRADED
+} from '../utils/constants';
+
+(function() {
+ 'use strict';
+ const LABEL = 'mdlext-selectfield__label';
+ const INPUT = 'mdlext-selectfield__select';
+
+ /**
+ * Class constructor for Selectfield MDLEXT component.
+ * Implements MDL component design pattern defined at:
+ * https://github.com/jasonmayes/mdl-component-design-pattern
+ *
+ * @constructor
+ * @param {HTMLElement} element The element that will be upgraded.
+ */
+ const MaterialExtSelectfield = function MaterialExtSelectfield(element) {
+ this.element_ = element;
+ this.init(); // Initialize instance.
+ };
+
+ window['MaterialExtSelectfield'] = MaterialExtSelectfield;
+
+ /**
+ * Handle focus.
+ *
+ * @param {Event} event The event that fired.
+ * @private
+ */
+ /*eslint no-unused-vars: 0*/
+ MaterialExtSelectfield.prototype.onFocus_ = function( /*event*/ ) {
+ this.element_.classList.add(IS_FOCUSED);
+ };
+
+ /**
+ * Handle lost focus.
+ *
+ * @param {Event} event The event that fired.
+ * @private
+ */
+ /*eslint no-unused-vars: 0*/
+ MaterialExtSelectfield.prototype.onBlur_ = function( /*event*/ ) {
+ this.element_.classList.remove(IS_FOCUSED);
+ };
+
+ /**
+ * Handle reset event from out side.
+ *
+ * @param {Event} event The event that fired.
+ * @private
+ */
+ MaterialExtSelectfield.prototype.onReset_ = function( /*event*/ ) {
+ this.updateClasses_();
+ };
+
+ /**
+ * Handle class updates.
+ *
+ * @private
+ */
+ MaterialExtSelectfield.prototype.updateClasses_ = function() {
+ this.checkDisabled();
+ this.checkValidity();
+ this.checkDirty();
+ this.checkFocus();
+ };
+
+ // Public methods.
+
+ /**
+ * Check the disabled state and update field accordingly.
+ *
+ * @public
+ */
+ MaterialExtSelectfield.prototype.checkDisabled = function() {
+ if (this.select_.disabled) {
+ this.element_.classList.add(IS_DISABLED);
+ } else {
+ this.element_.classList.remove(IS_DISABLED);
+ }
+ };
+ MaterialExtSelectfield.prototype['checkDisabled'] = MaterialExtSelectfield.prototype.checkDisabled;
+
+
+ /**
+ * Check the focus state and update field accordingly.
+ *
+ * @public
+ */
+ MaterialExtSelectfield.prototype.checkFocus = function() {
+ // Note: element.querySelector(':focus') always return null in JsDom, even if select element has focus
+ /*eslint no-extra-boolean-cast: 0*/
+ if (Boolean(this.element_.querySelector(':focus'))) {
+ this.element_.classList.add(IS_FOCUSED);
+ } else {
+ this.element_.classList.remove(IS_FOCUSED);
+ }
+ };
+
+ MaterialExtSelectfield.prototype['checkFocus'] = MaterialExtSelectfield.prototype.checkFocus;
+
+
+ /**
+ * Check the validity state and update field accordingly.
+ *
+ * @public
+ */
+ MaterialExtSelectfield.prototype.checkValidity = function() {
+
+ /* Don't think it makes any sense to check validity.
+ Tests I've done, so far, indicates that setting an illegal value via JS returns selectedIndex=0
+
+ if (this.select_.validity) {
+ if (this.select_.validity.valid) {
+ this.element_.classList.remove(this.CssClasses_.IS_INVALID);
+ } else {
+ this.element_.classList.add(this.CssClasses_.IS_INVALID);
+ }
+ }
+ */
+ };
+
+ MaterialExtSelectfield.prototype['checkValidity'] = MaterialExtSelectfield.prototype.checkValidity;
+
+ /**
+ * Check the dirty state and update field accordingly.
+ *
+ * @public
+ */
+ MaterialExtSelectfield.prototype.checkDirty = function() {
+ if (this.select_.value && this.select_.value.length > 0) {
+ this.element_.classList.add(IS_DIRTY);
+ } else {
+ this.element_.classList.remove(IS_DIRTY);
+ }
+ };
+
+ MaterialExtSelectfield.prototype['checkDirty'] = MaterialExtSelectfield.prototype.checkDirty;
+
+ /**
+ * Disable select field.
+ *
+ * @public
+ */
+ MaterialExtSelectfield.prototype.disable = function() {
+ this.select_.disabled = true;
+ this.updateClasses_();
+ };
+
+ MaterialExtSelectfield.prototype['disable'] = MaterialExtSelectfield.prototype.disable;
+
+ /**
+ * Enable select field.
+ *
+ * @public
+ */
+ MaterialExtSelectfield.prototype.enable = function() {
+ this.select_.disabled = false;
+ this.updateClasses_();
+ };
+
+ MaterialExtSelectfield.prototype['enable'] = MaterialExtSelectfield.prototype.enable;
+
+ /**
+ * Update select field value.
+ *
+ * @param {string} value The value to which to set the control (optional).
+ * @public
+ */
+ MaterialExtSelectfield.prototype.change = function(value) {
+ this.select_.value = value || '';
+ this.updateClasses_();
+ };
+ MaterialExtSelectfield.prototype['change'] = MaterialExtSelectfield.prototype.change;
+
+ /**
+ * Initialize element.
+ */
+ MaterialExtSelectfield.prototype.init = function() {
+ if (this.element_) {
+ this.label_ = this.element_.querySelector(`.${LABEL}`);
+ this.select_ = this.element_.querySelector(`.${INPUT}`);
+
+ if (this.select_) {
+ // Remove listeners, just in case ...
+ this.select_.removeEventListener('change', this.updateClasses_);
+ this.select_.removeEventListener('focus', this.onFocus_);
+ this.select_.removeEventListener('blur', this.onBlur_);
+ this.select_.removeEventListener('reset', this.onReset_);
+
+ this.select_.addEventListener('change', this.updateClasses_.bind(this));
+ this.select_.addEventListener('focus', this.onFocus_.bind(this));
+ this.select_.addEventListener('blur', this.onBlur_.bind(this));
+ this.select_.addEventListener('reset', this.onReset_.bind(this));
+
+ if(this.label_) {
+ let id;
+ if(!this.select_.hasAttribute('id')) {
+ id = `select-${randomString()}`;
+ this.select_.id = id;
+ }
+ else {
+ id = this.select_.id;
+ }
+
+ if(!this.label_.hasAttribute('for')) {
+ this.label_.setAttribute('for', id);
+ }
+ }
+
+ const invalid = this.element_.classList.contains(IS_INVALID);
+ this.updateClasses_();
+ this.element_.classList.add(IS_UPGRADED);
+
+ if (invalid) {
+ this.element_.classList.add(IS_INVALID);
+ }
+ if (this.select_.hasAttribute('autofocus')) {
+ this.element_.focus();
+ this.checkFocus();
+ }
+ }
+ }
+ };
+
+ /**
+ * Downgrade component
+ * E.g remove listeners and clean up resources
+ *
+ * Nothing to downgrade
+ *
+ MaterialExtSelectfield.prototype.mdlDowngrade_ = function() {
+ 'use strict';
+ console.log('***** MaterialExtSelectfield.mdlDowngrade ');
+ };
+ */
+
+ // The component registers itself. It can assume componentHandler is available
+ // in the global scope.
+ /*eslint no-undef: 0*/
+ componentHandler.register({
+ constructor: MaterialExtSelectfield,
+ classAsString: 'MaterialExtSelectfield',
+ cssClass: 'mdlext-js-selectfield',
+ widget: true
+ });
+})();
diff --git a/node_modules/mdl-ext/src/selectfield/snippets/selectfield.html b/node_modules/mdl-ext/src/selectfield/snippets/selectfield.html
new file mode 100644
index 0000000..d9bc5cd
--- /dev/null
+++ b/node_modules/mdl-ext/src/selectfield/snippets/selectfield.html
@@ -0,0 +1,113 @@
+<p>The<a href="https://developer.mozilla.org/en/docs/Web/HTML/Element/select" target="_blank">
+ HTML select</a> (<select>) element represents a control that presents a menu of options.
+ The options within the menu are represented by <option> elements, which can be grouped by
+ <optgroup> elements. Options can be pre-selected for the user.</p>
+
+<p>The Material Design Lite Ext (MDLEXT) <strong>select field</strong> component is an enhanced version of the standard
+ HTML <select> element. A select field consists of a horizontal line indicating where keyboard input
+ can occur and, typically, text that clearly communicates the intended contents of the select field.
+ An icon (at the right hand side) indicates that the select field has user selectable options.</p>
+
+<p><strong>Note: </strong>
+ The select field can for some browser and OS combinations, e.g. FireFox and OSX, be off by 2 pixels compared to the
+ input field. There is no way to fix this, as far as I know, without setting an explicit height on both field types.
+ Since MDL does not set a specific height of the text field, it can not be done for the select field either.
+ If alignment is required, the user must in his/hers design set a specific height both for textfields and selectfields.
+</p>
+
+<style scoped>
+ .selectelement-demo-container {
+ }
+ .selectelement-demo-container .mdl-cell {
+ padding: 0 4px 16px 0;
+ }
+ .selectelement-demo-container .mdl-cell p {
+ margin-bottom: 0;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+</style>
+
+<div class = "selectelement-demo-container">
+
+ <div class="mdl-grid mdl-grid--no-spacing">
+
+ <div class="mdl-cell mdl-cell--3-col">
+ <p>Selectfield component</p>
+ <div class="mdlext-selectfield mdlext-js-selectfield">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ <option value="option6">option 5 abcdefghijklmnopqrstuvw0123456789</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--3-col">
+ <p>Textfield component</p>
+ <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
+ <input class="mdl-textfield__input" type="text">
+ <label class="mdl-textfield__label">... to check alignment</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--3-col">
+ <p>Selectfield component with floating label</p>
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ <option value="option6">option 5 abcdefghijklmnopqrstuvw0123456789</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--3-col">
+ <p>Disabled selectfield component</p>
+ <div class="mdlext-selectfield mdlext-js-selectfield mdlext-selectfield--floating-label">
+ <select class="mdlext-selectfield__select" disabled>
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ <option value="option6">option 5 abcdefghijklmnopqrstuvw0123456789</option>
+ </select>
+ <label class="mdlext-selectfield__label">Profession</label>
+ </div>
+ </div>
+
+ <div class="mdl-cell mdl-cell--3-col">
+ <p>Unstyled select element</p>
+ <select style="width: 100%;">
+ <option value=""></option>
+ <option value="option1">option 1</option>
+ <option value="option2">option 2</option>
+ <option value="option3">option 3</option>
+ <option value="option4">option 4</option>
+ <option value="option5">option 5</option>
+ <option value="option6">option 5 abcdefghijklmnopqrstuvw0123456789</option>
+ </select>
+ <label>Profession</label>
+ </div>
+
+ <div class="mdl-cell mdl-cell--3-col">
+ <p>Unstyled input element</p>
+ <input type="text" style="width: 100%;">
+ <label>... to check alignment</label>
+ </div>
+
+ </div>
+</div>
diff --git a/node_modules/mdl-ext/src/sticky-header/_sticky-header.scss b/node_modules/mdl-ext/src/sticky-header/_sticky-header.scss
new file mode 100644
index 0000000..69a36f7
--- /dev/null
+++ b/node_modules/mdl-ext/src/sticky-header/_sticky-header.scss
@@ -0,0 +1,52 @@
+/**
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Use of this module requires the user to include variables from material-design-lite
+//@import "../../node_modules/material-design-lite/src/variables";
+//@import "../../node_modules/material-design-lite/src/mixins";
+@import "../variables";
+
+.mdlext-layout__sticky-header {
+ position: absolute;
+ overflow: visible;
+ background: $mdlext-sticky-header-background;
+ transition: 0.1s ease-in-out;
+
+ &.mdlext-is-scroll {
+ background: $mdlext-sticky-header-background-scroll;
+ }
+}
+
+*:not(.is-small-screen) .mdlext-layout__sticky-header {
+ .mdl-layout__drawer-button {
+ visibility: hidden;
+ }
+ .mdl-layout__header-row {
+ padding-left: $padding;
+ }
+}
+
+*:not(.mdl-layout--fixed-drawer).has-drawer .mdlext-layout__sticky-header,
+.is-small-screen.has-drawer .mdlext-layout__sticky-header {
+ display: flex;
+
+ .mdl-layout__drawer-button {
+ visibility: visible;
+ }
+ .mdl-layout__header-row {
+ padding-left: $padding + $layout-drawer-button-desktop-size;
+ }
+}
diff --git a/node_modules/mdl-ext/src/sticky-header/readme.md b/node_modules/mdl-ext/src/sticky-header/readme.md
new file mode 100644
index 0000000..e9b3107
--- /dev/null
+++ b/node_modules/mdl-ext/src/sticky-header/readme.md
@@ -0,0 +1,172 @@
+# Sticky Header
+
+![Sticky Header](../../etc/sticky-header.png)
+
+A sticky header can be used as a replacement for the Material Design Lite
+[Fixed Header](https://github.com/google/material-design-lite/tree/master/src/layout#examples).
+
+## Introduction
+A sticky header makes site navigation easily accessible anywhere on the page and saves content space at the same.
+
+The header should auto-hide, i.e. hiding the header automatically when a user starts scrolling down the page and
+bringing the header back when a user might need it: they reach the bottom of the page or start scrolling up.
+
+>**Note:** The Sticky Header does not collapse on smaller screens.
+
+### To include a MDLEXT **sticky-header** component:
+
+ 1. Code a `<div>` element. This is the "outer" div that holds the entire layout.
+```html
+<div>
+</div>
+```
+
+ 2. Add MDL classes as indicated, separated by spaces, to the `div` using the class attribute.
+```html
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+</div>
+```
+
+ 3. Inside the div, code a `<header>` element, as described in the Material Design Lite
+[Component Guide](https://getmdl.io/components/index.html#layout-section/layout). Add MDL classes as indicated.
+```html
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <header class="mdl-layout__header mdlext-layout__sticky-header mdlext-js-sticky-header">
+ <div class="mdl-layout__header-row">
+
+ <!-- Title -->
+ <span id="header-title" class="mdl-layout-title">Title goes here</span>
+
+ <!-- Add spacer, to align navigation to the right -->
+ <div class="mdl-layout-spacer"></div>
+
+ <label id="go-home" class="mdl-button mdl-js-button mdl-button--icon mdl-button--colored">
+ <a href="#">
+ <i class="material-icons">home</i>
+ </a>
+ </label>
+ </div>
+ </header>
+</div>
+```
+
+ 4. Code a drawer, and include the MDL class as indicated
+```html
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <header class="mdl-layout__header mdlext-layout__sticky-header mdlext-js-sticky-header">
+ <div class="mdl-layout__header-row">
+
+ <!-- Title -->
+ <span id="header-title" class="mdl-layout-title">Title goes here</span>
+
+ <!-- Add spacer, to align navigation to the right -->
+ <div class="mdl-layout-spacer"></div>
+
+ <label id="go-home" class="mdl-button mdl-js-button mdl-button--icon mdl-button--colored">
+ <a href="#">
+ <i class="material-icons">home</i>
+ </a>
+ </label>
+ </div>
+ </header>
+
+ <aside class="mdl-layout__drawer">
+ <span class="mdl-layout-title">Drawer title</span>
+ <nav class="mdl-navigation">
+ <a class="mdl-navigation__link" href="#">A manu item</a>
+ </nav>
+ </aside>
+</div>
+```
+
+ 4. Add a `<main>` element to hold the layout's primary content, and include the MDL class as indicated
+```html
+<div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer mdl-layout--fixed-header">
+ <header class="mdl-layout__header mdlext-layout__sticky-header mdlext-js-sticky-header">
+ <div class="mdl-layout__header-row">
+
+ <!-- Title -->
+ <span id="header-title" class="mdl-layout-title">Title goes here</span>
+
+ <!-- Add spacer, to align navigation to the right -->
+ <div class="mdl-layout-spacer"></div>
+
+ <label id="go-home" class="mdl-button mdl-js-button mdl-button--icon mdl-button--colored">
+ <a href="#">
+ <i class="material-icons">home</i>
+ </a>
+ </label>
+ </div>
+ </header>
+
+ <aside class="mdl-layout__drawer">
+ <span class="mdl-layout-title">Drawer title</span>
+ <nav class="mdl-navigation">
+ <a class="mdl-navigation__link" href="#">A manu item</a>
+ </nav>
+ </aside>
+
+ <main class="mdl-layout__content">
+ <p>Content</p>
+ <p>Goes</p>
+ <p>Here</p>
+ </main>
+</div>
+```
+
+### Examples
+
+* [Sticky header, Fixed drawer](http://leifoolsen.github.io/mdl-ext/demo/sticky-header.html)
+* [Sticky header, Drawer](http://leifoolsen.github.io/mdl-ext/demo/sticky-header-ii.html)
+* [Sticky header, No Drawer](http://leifoolsen.github.io/mdl-ext/demo/sticky-header-iii.html)
+* [Sticky header, Waterfall, Fiexed Drawer](http://leifoolsen.github.io/mdl-ext/demo/sticky-header-iv.html)
+* [Sticky header, Waterfall, Drawer](http://leifoolsen.github.io/mdl-ext/demo/sticky-header-v.html)
+* [Sticky header, Waterfall, No Drawer](http://leifoolsen.github.io/mdl-ext/demo/sticky-header-vi.html)
+
+
+## Component configuration
+The component can be configured using a `data-config` attribute. The attribute value is a JSON string with the following properties.
+
+| Property | | |
+|----------------------|----|----|
+| `visibleAtScrollEnd` | if `true`, the header vil show when page is scrolled to the bottom | default: `false` |
+
+
+The `data-config` attribute must be a valid JSON string. You can use single or double quotes for the JSON properties.
+
+Example 1, single quotes in JSON config string:
+```html
+<header class="mdl-layout__header mdlext-layout__sticky-header mdlext-js-sticky-header"
+ data-config="{ 'visibleAtScrollEnd': true }">
+
+ <div class="mdl-layout__header-row">
+ <span id="header-title" class="mdl-layout-title">Title goes here</span>
+ </div>
+</header>
+```
+
+Example 2, double quotes in JSON config string:
+```html
+<header class="mdl-layout__header mdlext-layout__sticky-header mdlext-js-sticky-header"
+ data-config='{ "visibleAtScrollEnd": true }'>
+
+ <div class="mdl-layout__header-row">
+ <span id="header-title" class="mdl-layout-title">Title goes here</span>
+ </div>
+</header>
+```
+
+## Configuration options
+
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements to the lightbox.
+The table below lists the available classes and their effects.
+
+| MDLEXT class | Effect | Remarks |
+|--------------|--------|---------|
+| `mdlext-layout__sticky-header` | Defines a header as an MDLEXT header component | Required on `<header>` element |
+| `mdlext-js-sticky-header` | Assigns basic MDL behavior to header | Required on `<header>` element |
+
+
+## How to use the component programmatically
+The [tests](../../test/sticky-header/sticky-header.spec.js) provides example code on how to use the component programmatically.
+
diff --git a/node_modules/mdl-ext/src/sticky-header/sticky-header.js b/node_modules/mdl-ext/src/sticky-header/sticky-header.js
new file mode 100644
index 0000000..9ed2e13
--- /dev/null
+++ b/node_modules/mdl-ext/src/sticky-header/sticky-header.js
@@ -0,0 +1,251 @@
+/**
+ * @license
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+/**
+ * A sticky header makes site navigation easily accessible anywhere on the page and saves content space at the same.
+ * The header should auto-hide, i.e. hiding the header automatically when a user starts scrolling down the page and
+ * bringing the header back when a user might need it: they reach the bottom of the page or start scrolling up.
+ */
+
+import fullThrottle from '../utils/full-throttle';
+import { jsonStringToObject } from '../utils/json-utils';
+import {
+ IS_UPGRADED
+} from '../utils/constants';
+
+
+(function() {
+ 'use strict';
+ const MDL_LAYOUT_CONTENT = 'mdl-layout__content';
+ const IS_SCROLL_CLASS = 'mdlext-is-scroll';
+
+
+ /**
+ * @constructor
+ * @param {Element} element The element that will be upgraded.
+ */
+ const MaterialExtStickyHeader = function MaterialExtStickyHeader(element) {
+ // Stores the element.
+ this.header_ = element;
+
+ // Heder listens to scroll events from content
+ this.content_ = null;
+ this.lastScrollTop_ = 0;
+
+ // Default config
+ this.config_ = {
+ visibleAtScrollEnd: false
+ };
+
+ this.mutationObserver_ = null;
+
+ this.drawing_ = false;
+
+ // Initialize instance.
+ this.init();
+ };
+
+ window['MaterialExtStickyHeader'] = MaterialExtStickyHeader;
+
+
+ /**
+ * Update header width
+ * @private
+ */
+ MaterialExtStickyHeader.prototype.recalcWidth_ = function() {
+ this.header_.style.width = `${this.content_.clientWidth}px`;
+ };
+
+ const throttleResize = fullThrottle(self => self.recalcWidth_() );
+
+ /**
+ * Adjust header width when window resizes or oreientation changes
+ * @param event
+ * @private
+ */
+ MaterialExtStickyHeader.prototype.resizeHandler_ = function( /* event */ ) {
+ throttleResize(this);
+ };
+
+
+ /**
+ * Update header position
+ * @private
+ */
+ MaterialExtStickyHeader.prototype.reposition_ = function() {
+
+ const currentContentScrollTop = this.content_.scrollTop;
+ const scrollDiff = this.lastScrollTop_ - currentContentScrollTop;
+
+ if(currentContentScrollTop <= 0) {
+ // Scrolled to the top. Header sticks to the top
+ this.header_.style.top = '0';
+ this.header_.classList.remove(IS_SCROLL_CLASS);
+ }
+ else if(scrollDiff > 0) {
+
+ if(scrollDiff >= this.header_.offsetHeight) {
+
+ // Scrolled up. Header slides in
+ const headerTop = (parseInt( window.getComputedStyle( this.header_ ).getPropertyValue( 'top' ) ) || 0);
+ if(headerTop != 0) {
+ this.header_.style.top = '0';
+ this.header_.classList.add(IS_SCROLL_CLASS);
+ }
+ this.lastScrollTop_ = currentContentScrollTop;
+ }
+ return;
+ }
+ else if(scrollDiff < 0) {
+ // Scrolled down
+ this.header_.classList.add(IS_SCROLL_CLASS);
+ let headerTop = (parseInt( window.getComputedStyle( this.header_ ).getPropertyValue( 'top' ) ) || 0);
+
+ if (this.content_.scrollHeight - this.content_.scrollTop <= this.content_.offsetHeight) {
+ // Bottom of content
+ if(headerTop != 0) {
+ this.header_.style.top = this.config_.visibleAtScrollEnd ? '0' : `-${this.header_.offsetHeight}px`;
+ }
+ }
+ else {
+ headerTop += scrollDiff;
+ const offsetHeight = this.header_.offsetHeight;
+ this.header_.style.top = `${( Math.abs( headerTop ) > offsetHeight ? -offsetHeight : headerTop )}px`;
+ }
+ }
+
+ this.lastScrollTop_ = currentContentScrollTop;
+ };
+
+
+ const throttleScroll = fullThrottle((self) => self.reposition_());
+
+ /**
+ * Scroll header when content scrolls
+ * @param event
+ * @private
+ */
+ MaterialExtStickyHeader.prototype.scrollHandler_ = function( /* event */ ) {
+ throttleScroll(this);
+ };
+
+ /**
+ * Init header position
+ * @private
+ */
+ MaterialExtStickyHeader.prototype.updatePosition_ = function( /* event */ ) {
+ this.recalcWidth_();
+ this.reposition_();
+ };
+
+ /**
+ * Add mutation observer
+ * @private
+ */
+ MaterialExtStickyHeader.prototype.addMutationObserver_ = function() {
+
+ // jsdom does not support MutationObserver - so this is not testable
+ /* istanbul ignore next */
+ this.mutationObserver_ = new MutationObserver( ( /*mutations*/ ) => {
+ // Adjust header width if content changes (e.g. in a SPA)
+ this.updatePosition_();
+ });
+
+ this.mutationObserver_.observe( this.content_, {
+ attributes: false,
+ childList: true,
+ characterData: false,
+ subtree: true
+ });
+ };
+
+ /**
+ * Removes event listeners
+ * @private
+ */
+ MaterialExtStickyHeader.prototype.removeListeners_ = function() {
+
+ window.removeEventListener('resize', this.resizeHandler_);
+ window.removeEventListener('orientationchange', this.resizeHandler_);
+
+ if(this.content_) {
+ this.content_.removeEventListener('scroll', this.scrollHandler_);
+ }
+
+ if(this.mutationObserver_) {
+ this.mutationObserver_.disconnect();
+ this.mutationObserver_ = null;
+ }
+ };
+
+ /**
+ * Initialize component
+ */
+ MaterialExtStickyHeader.prototype.init = function() {
+
+ if (this.header_) {
+
+ this.removeListeners_();
+
+ if(this.header_.hasAttribute('data-config')) {
+ this.config_ = jsonStringToObject(this.header_.getAttribute('data-config'));
+ }
+
+ this.content_ = this.header_.parentNode.querySelector(`.${MDL_LAYOUT_CONTENT}`) || null;
+
+ if(this.content_) {
+ this.content_.style.paddingTop = `${this.header_.offsetHeight}px`; // Make room for sticky header
+ this.lastScrollTop_ = this.content_.scrollTop;
+
+ this.content_.addEventListener('scroll', this.scrollHandler_.bind(this));
+ window.addEventListener('resize', this.resizeHandler_.bind(this));
+ window.addEventListener('orientationchange', this.resizeHandler_.bind(this));
+
+ this.addMutationObserver_();
+ this.updatePosition_();
+
+ // Set upgraded flag
+ this.header_.classList.add(IS_UPGRADED);
+ }
+ }
+ };
+
+ /*
+ * Downgrade component
+ * E.g remove listeners and clean up resources
+ *
+ * Nothing to clean
+ *
+ MaterialExtStickyHeader.prototype.mdlDowngrade_ = function() {
+ 'use strict';
+ console.log('***** MaterialExtStickyHeader.prototype.mdlDowngrade_');
+ };
+ */
+
+
+ // The component registers itself. It can assume componentHandler is available
+ // in the global scope.
+ /* eslint no-undef: 0 */
+ componentHandler.register({
+ constructor: MaterialExtStickyHeader,
+ classAsString: 'MaterialExtStickyHeader',
+ cssClass: 'mdlext-js-sticky-header'
+ });
+})();
diff --git a/node_modules/mdl-ext/src/utils/constants.js b/node_modules/mdl-ext/src/utils/constants.js
new file mode 100644
index 0000000..9e63ea7
--- /dev/null
+++ b/node_modules/mdl-ext/src/utils/constants.js
@@ -0,0 +1,62 @@
+'use strict';
+
+const VK_TAB = 9;
+const VK_ENTER = 13;
+const VK_ESC = 27;
+const VK_SPACE = 32;
+const VK_PAGE_UP = 33;
+const VK_PAGE_DOWN = 34;
+const VK_END = 35;
+const VK_HOME = 36;
+const VK_ARROW_LEFT = 37;
+const VK_ARROW_UP = 38;
+const VK_ARROW_RIGHT = 39;
+const VK_ARROW_DOWN = 40;
+
+const ARIA_EXPANDED = 'aria-expanded';
+const ARIA_HIDDEN = 'aria-hidden';
+const ARIA_MULTISELECTABLE = 'aria-multiselectable';
+const ARIA_SELECTED = 'aria-selected';
+
+const IS_DIRTY = 'is-dirty';
+const IS_DISABLED = 'is-disabled';
+const IS_EXPANDED = 'is-expanded';
+const IS_FOCUSED = 'is-focused';
+const IS_INVALID = 'is-invalid';
+const IS_UPGRADED = 'is-upgraded';
+const DATA_UPGRADED = 'data-upgraded';
+
+const MDL_RIPPLE = 'mdl-ripple';
+const MDL_RIPPLE_COMPONENT = 'MaterialRipple';
+const MDL_RIPPLE_EFFECT = 'mdl-js-ripple-effect';
+const MDL_RIPPLE_EFFECT_IGNORE_EVENTS = 'mdl-js-ripple-effect--ignore-events';
+
+export {
+ VK_TAB,
+ VK_ENTER,
+ VK_ESC,
+ VK_SPACE,
+ VK_PAGE_UP,
+ VK_PAGE_DOWN ,
+ VK_END,
+ VK_HOME,
+ VK_ARROW_LEFT,
+ VK_ARROW_UP,
+ VK_ARROW_RIGHT,
+ VK_ARROW_DOWN ,
+ ARIA_EXPANDED,
+ ARIA_HIDDEN,
+ ARIA_MULTISELECTABLE,
+ ARIA_SELECTED,
+ IS_DIRTY,
+ IS_DISABLED,
+ IS_EXPANDED,
+ IS_FOCUSED,
+ IS_INVALID,
+ IS_UPGRADED,
+ DATA_UPGRADED ,
+ MDL_RIPPLE,
+ MDL_RIPPLE_COMPONENT,
+ MDL_RIPPLE_EFFECT,
+ MDL_RIPPLE_EFFECT_IGNORE_EVENTS
+};
diff --git a/node_modules/mdl-ext/src/utils/debounce-function.js b/node_modules/mdl-ext/src/utils/debounce-function.js
new file mode 100644
index 0000000..68ce449
--- /dev/null
+++ b/node_modules/mdl-ext/src/utils/debounce-function.js
@@ -0,0 +1,66 @@
+/**
+ * Debouncing enforces that a function not be called again until a certain
+ * amount of time has passed without it being called.
+ *
+ * @see https://css-tricks.com/the-difference-between-throttling-and-debouncing/
+ * @see https://github.com/webmodules/raf-debounce
+ * @see https://github.com/moszeed/es6-promise-debounce
+ * @see https://gist.github.com/philbirnie/893950093611d5c1dff4246a572cfbeb/
+ * @see https://github.com/SliceMeNice-ES6/event-utils/blob/master/debounce.js
+ * @see https://github.com/jeromedecoster/raf-funcs
+ * @see http://unscriptable.com/2009/03/20/debouncing-javascript-methods/
+ * @see http://davidwalsh.name/javascript-debounce-function
+ *
+ * @param callback the callback
+ * @param threshold optional delay, default to 250 ms, min to 1000/60ms ms
+ * @param context optional context of this, default to global
+ * @return {Function} reference to immediate and cancel
+ */
+const MIN_THRESHOLD = 1000/60;
+
+const debounceFunction = function(callback, threshold=250, context) {
+
+ if(threshold < MIN_THRESHOLD) {
+ threshold = MIN_THRESHOLD;
+ }
+
+ if (!context) {
+ context = this || window;
+ }
+
+ let next = null;
+ let start = 0;
+
+ return function (...args) {
+
+ const cancel = () => {
+ if(next) {
+ window.cancelAnimationFrame(next);
+ next = null;
+ }
+ };
+
+ const execute = () => {
+ cancel();
+ return Reflect.apply(callback, context, args);
+ };
+
+ const later = () => {
+ if (threshold - (Date.now() - start) <= 0) {
+ return execute();
+ }
+ next = window.requestAnimationFrame(later);
+ };
+
+ cancel();
+ start = Date.now();
+ next = window.requestAnimationFrame(later);
+
+ return {
+ cancel: () => cancel(),
+ immediate: () => execute()
+ };
+ };
+};
+
+export default debounceFunction;
diff --git a/node_modules/mdl-ext/src/utils/dom-utils.js b/node_modules/mdl-ext/src/utils/dom-utils.js
new file mode 100644
index 0000000..5aa2658
--- /dev/null
+++ b/node_modules/mdl-ext/src/utils/dom-utils.js
@@ -0,0 +1,418 @@
+/**
+ * Remove child element(s)
+ * element.innerHTNL = '' has a performance penality!
+ * @see http://jsperf.com/empty-an-element/16
+ * @see http://jsperf.com/force-reflow
+ * @param element
+ * @param forceReflow
+ */
+const removeChildElements = (element, forceReflow = true) => {
+
+ // See: http://jsperf.com/empty-an-element/16
+ while (element.lastChild) {
+ element.removeChild(element.lastChild);
+ }
+ if(forceReflow) {
+ // See: http://jsperf.com/force-reflow
+ const d = element.style.display;
+
+ element.style.display = 'none';
+ element.style.display = d;
+ }
+};
+
+/**
+ * Moves child elements from a DOM node to another dom node.
+ * @param source {HTMLElement}
+ * @param target {HTMLElement} If the target parameter is ommited, a document fragment is created
+ * @return {HTMLElement} The target node
+ *
+ * @example
+ * // Moves child elements from a DOM node to another dom node.
+ * moveElements(source, destination);
+ *
+ * @example
+ * // If the second parameter is ommited, a document fragment is created:
+ * let fragment = moveElements(source);
+ *
+ * @See: https://github.com/webmodules/dom-move
+ */
+const moveElements = (source, target) => {
+ if (!target) {
+ target = source.ownerDocument.createDocumentFragment();
+ }
+ while (source.firstChild) {
+ target.appendChild(source.firstChild);
+ }
+ return target;
+};
+
+
+/**
+ * Get the browser viewport dimensions
+ * @see http://stackoverflow.com/questions/1248081/get-the-browser-viewport-dimensions-with-javascript
+ * @return {{windowWidth: number, windowHeight: number}}
+ */
+const getWindowViewport = () => {
+ return {
+ viewportWidth: Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0),
+ viewportHeight: Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0)
+ };
+};
+
+
+/**
+ * Check whether an element is in the window viewport
+ * @see http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport/
+ * @param top
+ * @param left
+ * @param bottom
+ * @param right
+ * @return {boolean} true if rectangle is inside window viewport, otherwise false
+ */
+const isRectInsideWindowViewport = ({ top, left, bottom, right }) => {
+ const { viewportWidth, viewportHeight } = getWindowViewport();
+ return top >= 0 &&
+ left >= 0 &&
+ bottom <= viewportHeight &&
+ right <= viewportWidth;
+};
+
+
+/**
+ * Get a list of parent elements that can possibly scroll
+ * @param el the element to get parents for
+ * @returns {Array}
+ */
+const getScrollParents = el => {
+ const elements = [];
+
+ /*
+ for (el = el.parentNode; el; el = el.parentNode) {
+ const cs = window.getComputedStyle(el);
+ if(!(cs.overflowY === 'hidden' && cs.overflowX === 'hidden')) {
+ elements.unshift(el);
+ }
+ if(el === document.body) {
+ break;
+ }
+ }
+ */
+
+ let element = el.parentNode;
+ while (element) {
+ const cs = window.getComputedStyle(element);
+ if(!(cs.overflowY === 'hidden' && cs.overflowX === 'hidden')) {
+ elements.unshift(element);
+ }
+ if(element === document.body) {
+ break;
+ }
+ element = element.parentNode;
+ }
+
+ return elements;
+};
+
+/**
+ * Get a list of parent elements, from a given element to a given element
+ * @param {HTMLElement} from
+ * @param {HTMLElement} to
+ * @return {Array<HTMLElement>} the parent elements, not including from and to
+ */
+const getParentElements = (from, to) => {
+ const result = [];
+ let element = from.parentNode;
+ while (element) {
+ if(element === to) {
+ break;
+ }
+ result.unshift(element);
+ element = element.parentNode;
+ }
+ return result;
+};
+
+/**
+ * Position element next to button
+ *
+ * Positioning strategy
+ * 1. element.height > viewport.height
+ * let element.height = viewport.heigt
+ * let element.overflow-y = auto
+ * 2. element.width > viewport.width
+ * let element.width = viewport.width
+ * 3. position element below button, align left edge of element with button left
+ * done if element inside viewport
+ * 4. position element below button, align right edge of element with button right
+ * done if element inside viewport
+ * 5. positions element above button, aligns left edge of element with button left
+ * done if element inside viewport
+ * 6. position element above the control element, aligned to its right.
+ * done if element inside viewport
+ * 7. position element at button right hand side, aligns element top with button top
+ * done if element inside viewport
+ * 8. position element at button left hand side, aligns element top with button top
+ * done if element inside viewport
+ * 9. position element inside viewport
+ * 1. position element at viewport bottom
+ * 2. position element at button right hand side
+ * done if element inside viewport
+ * 3. position element at button left hand side
+ * done if element inside viewport
+ * 4. position element at viewport right
+ * 10. done
+ *
+ */
+const tether = (controlledBy, element) => {
+ const controlRect = controlledBy.getBoundingClientRect();
+
+ // 1. will element height fit inside window viewport?
+ const { viewportWidth, viewportHeight } = getWindowViewport();
+
+ element.style.height = 'auto';
+ //element.style.overflowY = 'hidden';
+ if(element.offsetHeight > viewportHeight) {
+ element.style.height = `${viewportHeight}px`;
+ element.style.overflowY = 'auto';
+ }
+
+ // 2. will element width fit inside window viewport?
+ element.style.width = 'auto';
+ if(element.offsetWidth > viewportWidth) {
+ element.style.width = `${viewportWidth}px`;
+ }
+
+ const elementRect = element.getBoundingClientRect();
+
+ // element to control distance
+ const dy = controlRect.top - elementRect.top;
+ const dx = controlRect.left - elementRect.left;
+
+ // element rect, window coordinates relative to top,left of control
+ const top = elementRect.top + dy;
+ const left = elementRect.left + dx;
+ const bottom = top + elementRect.height;
+ const right = left + elementRect.width;
+
+ // Position relative to control
+ let ddy = dy;
+ let ddx = dx;
+
+ if(isRectInsideWindowViewport({
+ top: top + controlRect.height,
+ left: left,
+ bottom: bottom + controlRect.height,
+ right: right
+ })) {
+ // 3 position element below the control element, aligned to its left
+ ddy = controlRect.height + dy;
+ //console.log('***** 3');
+ }
+ else if(isRectInsideWindowViewport({
+ top: top + controlRect.height,
+ left: left + controlRect.width - elementRect.width,
+ bottom: bottom + controlRect.height,
+ right: left + controlRect.width
+ })) {
+ // 4 position element below the control element, aligned to its right
+ ddy = controlRect.height + dy;
+ ddx = dx + controlRect.width - elementRect.width;
+ //console.log('***** 4');
+ }
+ else if(isRectInsideWindowViewport({
+ top: top - elementRect.height,
+ left: left,
+ bottom: bottom - elementRect.height,
+ right: right
+ })) {
+ // 5. position element above the control element, aligned to its left.
+ ddy = dy - elementRect.height;
+ //console.log('***** 5');
+ }
+ else if(isRectInsideWindowViewport({
+ top: top - elementRect.height,
+ left: left + controlRect.width - elementRect.width,
+ bottom: bottom - elementRect.height,
+ right: left + controlRect.width
+ })) {
+ // 6. position element above the control element, aligned to its right.
+ ddy = dy - elementRect.height;
+ ddx = dx + controlRect.width - elementRect.width;
+ //console.log('***** 6');
+ }
+ else if(isRectInsideWindowViewport({
+ top: top,
+ left: left + controlRect.width,
+ bottom: bottom,
+ right: right + controlRect.width
+ })) {
+ // 7. position element at button right hand side
+ ddx = controlRect.width + dx;
+ //console.log('***** 7');
+ }
+ else if(isRectInsideWindowViewport({
+ top: top,
+ left: left - controlRect.width,
+ bottom: bottom,
+ right: right - controlRect.width
+ })) {
+ // 8. position element at button left hand side
+ ddx = dx - elementRect.width;
+ //console.log('***** 8');
+ }
+ else {
+ // 9. position element inside viewport, near controlrect if possible
+ //console.log('***** 9');
+
+ // 9.1 position element near controlrect bottom
+ ddy = dy - bottom + viewportHeight;
+ if(top + controlRect.height >= 0 && bottom + controlRect.height <= viewportHeight) {
+ ddy = controlRect.height + dy;
+ }
+ else if(top - elementRect.height >= 0 && bottom - elementRect.height <= viewportHeight) {
+ ddy = dy - elementRect.height;
+ }
+
+ if(left + elementRect.width + controlRect.width <= viewportWidth) {
+ // 9.2 Position element at button right hand side
+ ddx = controlRect.width + dx;
+ //console.log('***** 9.2');
+ }
+ else if(left - elementRect.width >= 0) {
+ // 9.3 Position element at button left hand side
+ ddx = dx - elementRect.width;
+ //console.log('***** 9.3');
+ }
+ else {
+ // 9.4 position element at (near) viewport right
+ const r = left + elementRect.width - viewportWidth;
+ ddx = dx - r;
+ //console.log('***** 9.4');
+ }
+ }
+
+ // 10. done
+ element.style.top = `${element.offsetTop + ddy}px`;
+ element.style.left = `${element.offsetLeft + ddx}px`;
+ //console.log('***** 10. done');
+};
+
+/**
+ * Check if the given element can receive focus
+ * @param {HTMLElement} element the element to check
+ * @return {boolean} true if the element is focusable, otherwise false
+ */
+const isFocusable = (element) => {
+ // https://github.com/stephenmathieson/is-focusable/blob/master/index.js
+ // http://stackoverflow.com/questions/1599660/which-html-elements-can-receive-focus
+
+ if (element.hasAttribute('tabindex')) {
+ const tabindex = element.getAttribute('tabindex');
+ if (!Number.isNaN(tabindex)) {
+ return parseInt(tabindex) > -1;
+ }
+ }
+
+ if (element.hasAttribute('contenteditable') &&
+ element.getAttribute('contenteditable') !== 'false') {
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes#attr-contenteditable
+ return true;
+ }
+
+ // natively focusable, but only when enabled
+ const selector = /input|select|textarea|button|details/i;
+ const name = element.nodeName;
+ if (selector.test(name)) {
+ return element.type.toLowerCase() !== 'hidden' && !element.disabled;
+ }
+
+ // anchors and area must have an href
+ if (name === 'A' || name === 'AREA') {
+ return !!element.href;
+ }
+
+ if (name === 'IFRAME') {
+ // Check visible iframe
+ const cs = window.getComputedStyle(element);
+ return cs.getPropertyValue('display').toLowerCase() !== 'none';
+ }
+
+ return false;
+};
+
+
+/**
+ * Get a list of offset parents for given element
+ * @see https://www.benpickles.com/articles/51-finding-a-dom-nodes-common-ancestor-using-javascript
+ * @param el the element
+ * @return {Array} a list of offset parents
+ */
+/*
+const offsetParents = (el) => {
+ const elements = [];
+ for (; el; el = el.offsetParent) {
+ elements.unshift(el);
+ }
+ if(!elements.find(e => e === document.body)) {
+ elements.unshift(document.body);
+ }
+ return elements;
+};
+*/
+
+/**
+ * Finds the common offset ancestor of two DOM nodes
+ * @see https://www.benpickles.com/articles/51-finding-a-dom-nodes-common-ancestor-using-javascript
+ * @see https://gist.github.com/benpickles/4059636
+ * @param a
+ * @param b
+ * @return {Element} The common offset ancestor of a and b
+ */
+/*
+const commonOffsetAncestor = (a, b) => {
+ const parentsA = offsetParents(a);
+ const parentsB = offsetParents(b);
+
+ for (let i = 0; i < parentsA.length; i++) {
+ if (parentsA[i] !== parentsB[i]) return parentsA[i-1];
+ }
+};
+*/
+
+/**
+ * Calculate position relative to a target element
+ * @see http://stackoverflow.com/questions/21064101/understanding-offsetwidth-clientwidth-scrollwidth-and-height-respectively
+ * @param target
+ * @param el
+ * @return {{top: number, left: number}}
+ */
+/*
+const calcPositionRelativeToTarget = (target, el) => {
+ let top = 0;
+ let left = 0;
+
+ while(el) {
+ top += (el.offsetTop - el.scrollTop + el.clientTop) || 0;
+ left += (el.offsetLeft - el.scrollLeft + el.clientLeft) || 0;
+ el = el.offsetParent;
+
+ if(el === target) {
+ break;
+ }
+ }
+ return { top: top, left: left };
+};
+*/
+
+export {
+ getWindowViewport,
+ getParentElements,
+ getScrollParents,
+ isFocusable,
+ isRectInsideWindowViewport,
+ moveElements,
+ removeChildElements,
+ tether,
+};
+
diff --git a/node_modules/mdl-ext/src/utils/easing.js b/node_modules/mdl-ext/src/utils/easing.js
new file mode 100644
index 0000000..fea208f
--- /dev/null
+++ b/node_modules/mdl-ext/src/utils/easing.js
@@ -0,0 +1,18 @@
+'use strict';
+
+// See: http://robertpenner.com/easing/
+
+const easeInOutQuad = (t, b, c, d) => {
+ t /= d / 2;
+ if(t < 1) return c / 2 * t * t + b;
+ t--;
+ return -c / 2 * (t * (t - 2) - 1) + b;
+};
+
+const inOutQuintic = (t, b, c, d) => {
+ const ts = (t/=d)*t;
+ const tc = ts*t;
+ return b+c*(6*tc*ts + -15*ts*ts + 10*tc);
+};
+
+export { easeInOutQuad, inOutQuintic };
diff --git a/node_modules/mdl-ext/src/utils/full-throttle.js b/node_modules/mdl-ext/src/utils/full-throttle.js
new file mode 100644
index 0000000..7cac3d7
--- /dev/null
+++ b/node_modules/mdl-ext/src/utils/full-throttle.js
@@ -0,0 +1,35 @@
+/**
+ * Since some events can fire at a high rate, the event handler should be limited to execute computationally
+ * expensive operations, such as DOM modifications, inside a single rendered frame.
+ * When listening to e.g. scroll and resize events, the browser tends to fire off more events per
+ * second than are actually useful. For instance, if your event listener sets some element positions, then it
+ * is possible for those positions to be updated multiple times in a single rendered frame. In this case, all of
+ * the layout calculations triggered by setting the elements' positions will be wasted except for the one time that
+ * it runs immediately prior to the browser rendering the updated layout to the screen.
+ * To avoid wasting cycles, we can use requestAnimationFrame to only run the event listener once just before the page
+ * is rendered to the screen.
+ * *
+ * @param callback the function to throttle
+ * @param context optional context of this, default to global
+ * @return {function(...[*])}
+ */
+const fullThrottle = (callback, context) => {
+
+ if (!context) {
+ context = this || window;
+ }
+
+ let throttling = false;
+
+ return (...args) => {
+ if(!throttling) {
+ throttling = true;
+ window.requestAnimationFrame( () => {
+ throttling = false;
+ return Reflect.apply(callback, context, args);
+ });
+ }
+ };
+};
+
+export default fullThrottle;
diff --git a/node_modules/mdl-ext/src/utils/index.js b/node_modules/mdl-ext/src/utils/index.js
new file mode 100644
index 0000000..c04972d
--- /dev/null
+++ b/node_modules/mdl-ext/src/utils/index.js
@@ -0,0 +1,7 @@
+import './constants';
+import './dom-utils';
+import './string-utils';
+import './json-utils';
+import './full-throttle';
+import './easing';
+import './interval-function';
diff --git a/node_modules/mdl-ext/src/utils/interval-function.js b/node_modules/mdl-ext/src/utils/interval-function.js
new file mode 100644
index 0000000..4c344e3
--- /dev/null
+++ b/node_modules/mdl-ext/src/utils/interval-function.js
@@ -0,0 +1,83 @@
+const MIN_INERVAL = 1000/60;
+
+/**
+ * Trigger a callback at a given interval
+ * @param interval defaults to 1000/60 ms
+ * @return {function()} reference to start, stop, immediate and started
+ */
+
+const intervalFunction = ( interval = MIN_INERVAL ) => {
+
+ let lapse = interval < MIN_INERVAL ? MIN_INERVAL : interval;
+ let cb = undefined;
+ let next = null;
+ let timeElapsed = 0;
+
+ const execute = () => {
+ const f = cb(timeElapsed);
+ if (!f) {
+ cancel();
+ }
+ };
+
+ const cancel = () => {
+ if(next) {
+ window.cancelAnimationFrame(next);
+ }
+ next = null;
+ timeElapsed = 0;
+ };
+
+ const start = () => {
+ let timeStart = Date.now();
+
+ const loop = now => {
+ if (next) {
+ next = window.requestAnimationFrame( () => loop( Date.now() ));
+
+ timeElapsed += now - timeStart;
+
+ if(timeElapsed >= lapse) {
+ execute();
+ if( (timeElapsed -= lapse) > lapse) {
+ // time elapsed - interval_ > interval_ , indicates inactivity
+ // Could be due to browser minimized, tab changed, screen saver started, computer sleep, and so on
+ timeElapsed = 0;
+ }
+ }
+ timeStart = now;
+ }
+ };
+
+ next = 1; // a truthy value for first loop
+ loop( timeStart );
+ };
+
+ return {
+ get started() {
+ return next != null;
+ },
+ get interval() {
+ return lapse;
+ },
+ set interval(value) {
+ lapse = value < MIN_INERVAL ? MIN_INERVAL : value;
+ },
+ start(callback) {
+ if(typeof callback !== 'function') {
+ throw new TypeError('callback parameter must be a function');
+ }
+ cb = callback;
+ start();
+ },
+ immediate() {
+ if(!cb) {
+ throw new ReferenceError('callback parameter is not defined. Call start before immediate.');
+ }
+ execute();
+ },
+ stop: () => cancel(),
+ };
+};
+
+export default intervalFunction;
diff --git a/node_modules/mdl-ext/src/utils/json-utils.js b/node_modules/mdl-ext/src/utils/json-utils.js
new file mode 100644
index 0000000..c6f6c77
--- /dev/null
+++ b/node_modules/mdl-ext/src/utils/json-utils.js
@@ -0,0 +1,18 @@
+'use strict';
+
+/**
+ * Converts a JSON string to object
+ * @param jsonString
+ * @param source
+ */
+const jsonStringToObject = (jsonString, source = {} ) => {
+ const s = jsonString.replace(/'/g, '"');
+ try {
+ return Object.assign(source, JSON.parse(s));
+ }
+ catch (e) {
+ throw new Error(`Failed to parse json string: ${s}. Error: ${e.message}`);
+ }
+};
+
+export { jsonStringToObject };
diff --git a/node_modules/mdl-ext/src/utils/resize-observer.js b/node_modules/mdl-ext/src/utils/resize-observer.js
new file mode 100644
index 0000000..b69e2f2
--- /dev/null
+++ b/node_modules/mdl-ext/src/utils/resize-observer.js
@@ -0,0 +1,294 @@
+
+/**
+ * An API for observing changes to Element’s size.
+ *
+ * @See https://wicg.github.io/ResizeObserver/
+ * @ee https://github.com/pelotoncycle/resize-observer
+ *
+ */
+
+import intervalFunction from './interval-function';
+
+((window, document) => {
+ 'use strict';
+
+ if (typeof window.ResizeObserver !== 'undefined') {
+ return;
+ }
+
+ document.resizeObservers = [];
+
+ /**
+ * The content rect is defined in section 2.3 ResizeObserverEntry of the spec
+ * @param target the element to calculate the content rect for
+ * @return {{top: (Number|number), left: (Number|number), width: number, height: number}}
+ *
+ * Note:
+ * Avoid using margins on the observed element. The calculation can return incorrect values when margins are involved.
+ *
+ * The following CSS will report incorrect width (Chrome OSX):
+ *
+ * <div id="outer" style="width: 300px; height:300px; background-color: green;overflow:auto;">
+ * <div id="observed" style="width: 400px; height:400px; background-color: yellow; margin:30px; border: 20px solid red; padding:10px;">
+ * </div>
+ * </div>
+ *
+ * The calculated width is 280. The actual (correct) width is 340 since Chrome clips the margin.
+ *
+ * Use an outer container if you really need a "margin":
+ *
+ * <div id="outer" style="width: 300px; height:300px; background-color: green;overflow:auto; padding:30px;">
+ * <div id="observed" style="width: 400px; height:400px; background-color: yellow; margin: 0; border: 20px solid red; padding:10px;">
+ * </div>
+ * </div>
+ *
+ * A more detailed explanation can be fund here:
+ * http://stackoverflow.com/questions/21064101/understanding-offsetwidth-clientwidth-scrollwidth-and-height-respectively
+ */
+ const getContentRect = target => {
+ const cs = window.getComputedStyle(target);
+ const r = target.getBoundingClientRect();
+ const top = parseFloat(cs.paddingTop) || 0;
+ const left = parseFloat(cs.paddingLeft) || 0;
+ const width = r.width - (
+ (parseFloat(cs.marginLeft) || 0) +
+ (parseFloat(cs.marginRight) || 0) +
+ (parseFloat(cs.borderLeftWidth) || 0) +
+ (parseFloat(cs.borderRightWidth) || 0) +
+ (left) +
+ (parseFloat(cs.paddingRight) || 0)
+ );
+ const height = r.height - (
+ (parseFloat(cs.marginTop) || 0) +
+ (parseFloat(cs.marginBottom) || 0) +
+ (parseFloat(cs.borderTopWidth) || 0) +
+ (parseFloat(cs.borderBottomWidth) || 0) +
+ (top) +
+ (parseFloat(cs.paddingBottom) || 0)
+ );
+ return {width: width, height: height, top: top, left: left};
+ };
+
+ const dimensionHasChanged = (target, lastWidth, lastHeight) => {
+ const {width, height} = getContentRect(target);
+ return width !== lastWidth || height !== lastHeight;
+ };
+
+
+ /**
+ * ResizeObservation holds observation information for a single Element.
+ * @param target
+ * @return {{target: *, broadcastWidth, broadcastHeight, isOrphan: (function()), isActive: (function())}}
+ * @constructor
+ */
+ const ResizeObservation = target => {
+ const {width, height} = getContentRect(target);
+
+ return {
+ target: target,
+ broadcastWidth: width,
+ broadcastHeight: height,
+
+ isOrphan() {
+ return !this.target || !this.target.parentNode;
+ },
+ isActive() {
+ return dimensionHasChanged(this.target, this.broadcastWidth, this.broadcastHeight);
+ }
+ };
+ };
+
+ /**
+ * A snapshot of the observed element
+ * @param target
+ * @param rect
+ * @return {{target: *, contentRect: *}}
+ * @constructor
+ */
+ const ResizeObserverEntry = (target, rect) => {
+ return {
+ target: target,
+ contentRect: rect
+ };
+ };
+
+
+ /**
+ * The ResizeObserver is used to observe changes to Element's content rect.
+ */
+ class ResizeObserver {
+
+ /**
+ * Constructor for instantiating new Resize observers.
+ * @param callback void (sequence<ResizeObserverEntry> entries). The function which will be called on each resize.
+ * @throws {TypeError}
+ */
+ constructor( callback ) {
+
+ if(typeof callback !== 'function') {
+ throw new TypeError('callback parameter must be a function');
+ }
+
+ this.callback_ = callback;
+ this.observationTargets_ = [];
+ this.activeTargets_ = [];
+
+ document.resizeObservers.push(this);
+ }
+
+ /**
+ * A list of ResizeObservations. It represents all Elements being observed.
+ *
+ * @return {Array}
+ */
+ get observationTargets() {
+ return this.observationTargets_;
+ }
+
+ /**
+ * A list of ResizeObservations. It represents all Elements whose size has
+ * changed since last observation broadcast that are eligible for broadcast.
+ *
+ * @return {Array}
+ */
+ get activeTargets() {
+ return this.activeTargets_;
+ }
+
+ /**
+ * Adds target to the list of observed elements.
+ * @param {HTMLElement} target The target to observe
+ */
+ observe(target) {
+ if(target) {
+ if (!(target instanceof HTMLElement)) {
+ throw new TypeError('target parameter must be an HTMLElement');
+ }
+ if (!this.observationTargets_.find(t => t.target === target)) {
+ this.observationTargets_.push(ResizeObservation(target));
+ resizeController.start();
+ }
+ }
+ }
+
+ /**
+ * Removes target from the list of observed elements.
+ * @param target The target to remove
+ */
+ unobserve(target) {
+ const i = this.observationTargets_.findIndex(t => t.target === target);
+ if(i > -1) {
+ this.observationTargets_.splice(i, 1);
+ }
+ }
+
+ /**
+ * Stops the ResizeObserver instance from receiving notifications of resize changes.
+ * Until the observe() method is used again, observer's callback will not be invoked.
+ */
+ disconnect() {
+ this.observationTargets_ = [];
+ this.activeTargets_ = [];
+ }
+
+ /**
+ * Removes the ResizeObserver from the list of observers
+ */
+ destroy() {
+ this.disconnect();
+ const i = document.resizeObservers.findIndex(o => o === this);
+ if(i > -1) {
+ document.resizeObservers.splice(i, 1);
+ }
+ }
+
+ deleteOrphansAndPopulateActiveTargets_() {
+
+ // Works, but two iterations
+ //this.observationTargets_ = this.observationTargets_.filter( resizeObervation => !resizeObervation.isOrphan());
+ //this.activeTargets_ = this.observationTargets_.filter( resizeObervation => resizeObervation.isActive());
+
+ // Same result as above, one iteration
+ /*
+ this.activeTargets_ = [];
+ let n = this.observationTargets_.length-1;
+ while(n >= 0) {
+ if(this.observationTargets_[n].isOrphan()) {
+ this.observationTargets_.splice(n, 1);
+ }
+ else if(this.observationTargets_[n].isActive()) {
+ this.activeTargets_.push(this.observationTargets_[n]);
+ }
+ n -= 1;
+ }
+ */
+
+ // Same result as above - but reduce is cooler :-)
+ this.activeTargets_ = this.observationTargets_.reduceRight( (prev, resizeObservation, index, arr) => {
+ if(resizeObservation.isOrphan()) {
+ arr.splice(index, 1);
+ }
+ else if(resizeObservation.isActive()) {
+ prev.push(resizeObservation);
+ }
+ return prev;
+ }, []);
+ }
+
+ broadcast_() {
+ this.deleteOrphansAndPopulateActiveTargets_();
+ if (this.activeTargets_.length > 0) {
+ const entries = [];
+ for (const resizeObservation of this.activeTargets_) {
+ const rect = getContentRect(resizeObservation.target);
+ resizeObservation.broadcastWidth = rect.width;
+ resizeObservation.broadcastHeight = rect.height;
+ entries.push(ResizeObserverEntry(resizeObservation.target, rect));
+ }
+ this.callback_(entries);
+ this.activeTargets_ = [];
+ }
+ }
+ }
+
+
+ //let interval = require('./interval-function');
+
+ /**
+ * Broadcasts Element.resize events
+ * @return {{start: (function()), stop: (function())}}
+ * @constructor
+ */
+ const ResizeController = () => {
+
+ const shouldStop = () => {
+ return document.resizeObservers.findIndex( resizeObserver => resizeObserver.observationTargets.length > 0 ) > -1;
+ };
+
+ const execute = () => {
+ //console.log('***** Execute');
+ for(const resizeObserver of document.resizeObservers) {
+ resizeObserver.broadcast_();
+ }
+
+ return shouldStop();
+ };
+
+ const interval = intervalFunction(200);
+
+ return {
+ start() {
+ if(!interval.started) {
+ //console.log('***** Start poll');
+ interval.start(execute);
+ }
+ }
+ };
+ };
+
+ window.ResizeObserver = ResizeObserver;
+
+ const resizeController = ResizeController();
+ //console.log('***** ResizeObserver ready');
+
+})(window, document);
diff --git a/node_modules/mdl-ext/src/utils/snippets/resize-observer.html b/node_modules/mdl-ext/src/utils/snippets/resize-observer.html
new file mode 100644
index 0000000..5d956c2
--- /dev/null
+++ b/node_modules/mdl-ext/src/utils/snippets/resize-observer.html
@@ -0,0 +1,221 @@
+<!-- See: https://github.com/WICG/ResizeObserver/blob/master/demo.html -->
+
+<style>
+ .resize {
+ border: 2em solid rgba(0,255,0, 0.5);
+ background-color: #DDD;
+ width: 90%; //300.49px;
+ height: 200.5px;
+ overflow: hidden;
+ position:relative;
+ display:inline-block;
+ }
+ .yellowBorder {
+ border-width: 1px;
+ border-style: solid;
+ }
+
+ .maptiles {
+ overflow: hidden;
+ }
+
+ .maptiles::after {
+ content: "map tiles";
+ position: relative;
+ top: 20px;
+ }
+
+ .elipse {
+ border: 20px solid rgba(100,255,100, 0.5);
+ }
+ .elipse::after {
+ content: "canvas";
+ position: relative;
+ top: -100px;
+ }
+ .domMunch {
+ background-color: orange;
+ }
+ .domMunch > div {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ border: 1px solid black;
+ }
+ .domMunch::after {
+ content: "domMunch";
+ position: relative;
+ top: 20px;
+ }
+
+ .toolbar {
+ margin: 16px 0;
+ position: relative;
+ display: flex;
+ align-items: center;
+ }
+
+ .toolbar > * {
+ margin-right: 8px;
+ min-width: 110px;
+ width: auto;
+ }
+
+ .toolbar > span {
+ flex-grow: 1;
+ text-align: right;
+ font-weight: 600;
+ font-size: 1.2em;
+ }
+</style>
+
+<h1 style="display:none">ResizeObserver unexpected error</h1>
+<pre id="log" style="display:none">log:</pre>
+
+<section class="toolbar">
+ <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect">
+ <input id="cb-observe" type="checkbox" class="mdl-checkbox__input" checked>
+ <span class="mdl-checkbox__label">Observe</span>
+ </label>
+
+ <div id="input-inc-container" class="mdl-textfield mdl-textfield--floating-label mdl-js-textfield">
+ <input id="input-inc" class="mdl-textfield__input" type="number" min="1" max="40" value="10">
+ <label class="mdl-textfield__label">Size increment</label>
+ </div>
+
+ <button id="btn-grow" class="cmd-button mdl-button mdl-js-button mdl-button--raised">Grow</button>
+ <button id="btn-shrink" class="cmd-button mdl-button mdl-js-button mdl-button--raised">Shrink</button>
+ <button id="btn-delete" class="cmd-button mdl-button mdl-js-button mdl-button--raised">Delete observed element</button>
+
+ <span id="observe-notification">
+ </span>
+</section>
+
+
+<div id="observed-element" class="resize maptiles" ></div>
+
+<script>
+ 'use strict';
+
+ (function() {
+ 'use strict';
+ document.addEventListener('DOMContentLoaded', function() {
+
+ if (!window.ResizeObserver) {
+ throw new Error('no window.ResizeObserver');
+ }
+
+ function log(msg) {
+ var e = document.querySelector('#log');
+ e.textContent = e.innerText + '\n' + msg;
+ }
+
+ function nextColor() {
+ return '#'+Math.random().toString(16).substr(-6);
+ }
+
+ function grow() {
+ var inc = parseInt(document.querySelector('#input-inc').value);
+ var elements = document.querySelectorAll('.resize');
+ for (var i = 0; i < elements.length; i++) {
+ var el = elements[i];
+ var s = window.getComputedStyle(el);
+ var w = parseFloat(s.width);
+ var h = parseFloat(s.height);
+ el.style.width = (w + inc) + 'px';
+ el.style.height = (h + inc * 2 / 3) + 'px';
+ }
+ }
+
+ function shrink() {
+ var dec = parseInt(document.querySelector('#input-inc').value);
+ var elements = document.querySelectorAll('.resize');
+ for (var i = 0; i < elements.length; i++) {
+ var el = elements[i];
+ var s = window.getComputedStyle(el);
+ var w = parseFloat(s.width);
+ var h = parseFloat(s.height);
+ el.style.width = (w - dec) + 'px';
+ el.style.height = (h - dec * 2 / 3) + 'px';
+ }
+ }
+
+
+ function initResizeHandlers() {
+ var elements = document.querySelectorAll('.maptiles');
+ for (var i = 0; i < elements.length; i++) {
+ elements[i].onresize = function() { this.style.borderColor = nextColor() };
+ }
+ }
+
+ function displayNotification(value) {
+ var notification = document.querySelector("#observe-notification");
+ notification.style.color = nextColor();
+ if(Number.isInteger(value)) {
+ notification.innerHTML = '<span>Observed: ' + value + ' element' + (value > 1 ? 's' : '') + '</span>';
+ }
+ else {
+ notification.innerHTML = '<span>Observer: ' + value + '</span>';
+ }
+ }
+
+ //
+ // Init
+ //
+ window.addEventListener('error', function (e) {
+ var error = e.error;
+ console.log(error);
+ log(error);
+ });
+
+
+ var ro = new ResizeObserver( function(entries) {
+
+ displayNotification(entries.length);
+
+ for (var i = 0; i < entries.length; i++) {
+ var entry = entries[i];
+ if (!entry.target || !entry.target.parentNode) {
+ throw new Error("detected resize on orphan element");
+ }
+ if (entry.target.onresize) {
+ entry.target.onresize(entry);
+ }
+ }
+ });
+
+ function toggleObserve() {
+ var isObserve = document.querySelector('#cb-observe').checked;
+ displayNotification(isObserve ? 'on' : 'off');
+
+ var elements = document.querySelectorAll('.resize');
+ if (isObserve) {
+ for (var i = 0; i < elements.length; i++) {
+ ro.observe(elements[i]);
+ }
+ }
+ else {
+ for (var i = 0; i < elements.length; i++) {
+ ro.unobserve(elements[i]);
+ }
+ }
+ }
+
+ function deleteObservedElement() {
+ var el = document.querySelector('#observed-element');
+ el.parentNode.removeChild(el);
+ }
+
+
+ document.querySelector('#cb-observe').addEventListener('click', function() { toggleObserve() });
+ document.querySelector('#btn-grow').addEventListener('click', function() { grow() });
+ document.querySelector('#btn-shrink').addEventListener('click', function() { shrink() });
+ document.querySelector('#btn-delete').addEventListener('click', function() { deleteObservedElement() });
+
+ // Start
+ initResizeHandlers()
+ toggleObserve();
+ });
+
+ }());
+</script>
diff --git a/node_modules/mdl-ext/src/utils/string-utils.js b/node_modules/mdl-ext/src/utils/string-utils.js
new file mode 100644
index 0000000..38830cc
--- /dev/null
+++ b/node_modules/mdl-ext/src/utils/string-utils.js
@@ -0,0 +1,76 @@
+'use strict';
+
+/**
+ * @license
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * A javascript utility for conditionally creating a list of strings.
+ * The function takes any number of arguments which can be a string or object.
+ * Inspired by (but not copied from) JedWatson/classnames, https://github.com/JedWatson/classnames
+ *
+ * @param {*} args the strings and/or objects to
+ * @return {Array} a list of strings
+ * @example
+ * // Returns ['foo', 'bar', 'baz', 'quux']
+ * stringList(', ', 'foo', { bar: true, duck: false }, 'baz', { quux: true });
+ * @example see the tests for more examples
+ */
+const stringList = (...args) => {
+
+ const isString = str => str != null && typeof str === 'string';
+
+ const flatten = list => list.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []);
+
+ const objectToStrings = arg =>
+ Object.keys(arg)
+ .filter(key => arg[key])
+ .map(key => key);
+
+ return args
+ .filter(arg => !!arg)
+ .map(arg => isString(arg) ? arg : objectToStrings(arg))
+ .reduce((result, arg) => result.concat(Array.isArray(arg) ? flatten(arg) : arg), []);
+};
+
+/**
+ * A simple javascript utility for conditionally joining strings together.
+ * The function takes a delimiter string and any number of arguments which can be a string or object.
+ *
+ * @param delimiter delimiter to separate joined strings
+ * @param {*} args the strings and/or objects to join
+ * @return {String} the joined strings
+ * @example
+ * // Returns 'foo, bar, baz, quux'
+ * joinStrings(', ', 'foo', { bar: true, duck: false }, 'baz', { quux: true });
+ * @example see the tests for more examples
+ */
+const joinStrings = (delimiter = ' ', ...args) => stringList(...args).join(delimiter);
+
+/**
+ * Generates a random string with a given length
+ * @param n {Integer} length of generated string
+ * @see http://stackoverflow.com/questions/1349404/generate-random-string-characters-in-javascript
+ * @return {String} the random string
+ * @example
+ * // Returns e.g. 'pd781w0y'
+ * randomString(8);
+ * @example see the tests for more examples
+ */
+const randomString = ( n=12 ) => Array( n+1 ).join((`${Math.random().toString(36)}00000000000000000`).slice(2, 18)).slice(0, n);
+
+export { joinStrings, randomString, stringList };
+
diff --git a/node_modules/mdl-ext/src/utils/throttle-function.js b/node_modules/mdl-ext/src/utils/throttle-function.js
new file mode 100644
index 0000000..f236ec3
--- /dev/null
+++ b/node_modules/mdl-ext/src/utils/throttle-function.js
@@ -0,0 +1,61 @@
+/**
+ * Throttling enforces a maximum number of times a function can be called over time.
+ *
+ * @param callback the function to throttle
+ * @param delay optional delay, default to 1000/60ms
+ * @param context optional context of this, default to global window
+ * @returns {Function} reference to immediate and cancel functions
+ * @see https://developer.mozilla.org/en-US/docs/Web/Events/resize#Example
+ * @see https://gist.github.com/yoavniran/d1d33f278bb7744d55c3
+ * @see https://github.com/pelotoncycle/frame-throttle
+ * @see https://github.com/jeromedecoster/raf-funcs
+ */
+const MIN_DELAY = 1000/60;
+
+const throttleFunction = (callback, delay=MIN_DELAY, context) => {
+
+ if(delay < MIN_DELAY) {
+ delay = MIN_DELAY;
+ }
+
+ if (!context) {
+ context = this || window;
+ }
+
+ let next = null;
+ let start = 0;
+
+ return (...args) => {
+
+ const cancel = () => {
+ if(next !== null) {
+ window.cancelAnimationFrame(next);
+ next = null;
+ }
+ };
+
+ const execute = () => {
+ cancel();
+ return Reflect.apply(callback, context, args);
+ };
+
+ const later = () => {
+ if (delay - (Date.now() - start) <= 0) {
+ return execute();
+ }
+ next = window.requestAnimationFrame(later);
+ };
+
+ if(next === null) {
+ start = Date.now();
+ next = window.requestAnimationFrame(later);
+ }
+
+ return {
+ cancel: () => cancel(),
+ immediate: () => execute()
+ };
+ };
+};
+
+export default throttleFunction;