Project import generated by Copybara.
GitOrigin-RevId: 63746295f1a5ab5a619056791995793d65529e62
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>