Merge branch 'feat/modals' into 'master'

added modal widget

See merge request !16
This commit is contained in:
Felix Hamann 2018-03-29 00:06:03 +02:00
commit 6652b4d563
8 changed files with 173 additions and 0 deletions

View File

@ -399,6 +399,12 @@ defaultMenuLayout menu widget = do
asidenav = $(widgetFile "widgets/asidenav")
breadcrumbs :: Widget
breadcrumbs = $(widgetFile "widgets/breadcrumbs")
modal :: [Char] -> [Char] -> Widget
modal modalTrigger modalContent = do
let
modalId :: Int32
modalId = 13
$(widgetFile "widgets/modal")
pc <- widgetToPageContent $ do
addStylesheetRemote "https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,800,900"

View File

@ -6,6 +6,8 @@
<!-- secondary navigation at the side -->
^{asidenav}
^{modal ".toggler" "Sit quis culpa eiusmod consectetur laborum aliquip consequat nisi exercitation eu pariatur laboris elit sit. Incididunt nulla quis sint duis ut ipsum incididunt magna. Pariatur aliquip fugiat exercitation non irure sunt id id cillum in nisi. Ad dolor qui enim ad labore est pariatur dolor occaecat excepteur ex labore exercitation velit laborum amet cupidatat. Pariatur veniam proident minim cillum ad sint ad officia cillum deserunt dolore mollit commodo exercitation. Anim laborum non sunt exercitation labore cupidatat amet aliquip ex anim ut do voluptate voluptate tempor."}
<div .main__content>
<!-- alerts -->

View File

@ -67,3 +67,8 @@
Knopf-Test:
<form .form-inline method=post action=@{HomeR} enctype=#{btnEnctype}>
^{btnWdgt}
<hr>
<div>
<div .toggler>
^{lipsum}

View File

@ -156,6 +156,11 @@ document.addEventListener('DOMContentLoaded', function() {
// setup reactive labels
Array.from(document.querySelectorAll('.reactive-label')).forEach(function(label) {
var input = document.querySelector('#' + label.getAttribute('for'));
if (!input) {
console.error('No input found for ReactiveLabel! Targeted input: \'#%s\'', label.getAttribute('for'));
return false;
}
var parent = label.parentElement;
var type = input.getAttribute('type');
var isFileInput = /file/i.test(type);

View File

@ -196,6 +196,8 @@ input[type="checkbox"]:checked::after {
color: var(--fontsec);
transform: translate(0, 0);
transition: all .1s;
display: inline-block;
width: 30%;
}
.reactive-label--small {
cursor: default;
@ -211,6 +213,7 @@ input[type="checkbox"]:checked::after {
.reactive-label {
position: relative;
transform: translate(2px, 30px);
display: block;
}
.reactive-label--small {
transform: translate(2px, 0px);

View File

@ -0,0 +1,15 @@
<div .modal.js-modal #modal-#{modalId} data-trigger=#{modalTrigger} data-closeable=true>
$# #{modalContent}
<h2>Neue Veranstaltung
<form>
<div .form-group>
<label .reactive-label for="inp1">Name
<input type="text" id="inp1">
<div .form-group>
<label .reactive-label for="inp2">Kürzel
<input type="text" id="inp2">
<div .form-group>
<label .reactive-label for="inp3">Semester
<input type="text" id="inp3">
<div .form-group>
<input type="submit" value="Submit">

View File

@ -0,0 +1,57 @@
document.addEventListener('DOMContentLoaded', function() {
'use strict';
window.utils = window.utils || {};
if (!window.utils.modal) {
window.utils.modal = function(modal) {
var overlay = document.createElement('div');
var closer = document.createElement('div');
var trigger = document.querySelector(modal.dataset.trigger);
var closeBound;
this.open = function openFn() {
modal.classList.add('modal--open');
overlay.classList.add('modal__overlay');
modal.parentNode.insertBefore(overlay, modal);
overlay.classList.add('modal__overlay--open');
toggleScroll(false);
if (modal.dataset.closeable === 'true') {
closer.classList.add('modal__closer');
modal.insertBefore(closer, null);
closer.addEventListener('click', closeBound, false);
overlay.addEventListener('click', closeBound, false);
}
};
this.openOnEvent = function openOnEventFn(event) {
if (event.detail.for === modal.getAttribute('id')) {
this.open();
}
};
this.close = function closeFn(event) {
if (typeof event === 'undefined' || event.target === closer || event.target === overlay) {
modal.classList.remove('modal--open');
overlay.classList.remove('modal__overlay--open');
toggleScroll(true);
closer.removeEventListener('click', closeBound, false);
}
};
document.addEventListener('modal-open', this.openOnEvent.bind(this), false);
closeBound = this.close.bind(this);
if (trigger) {
trigger.classList.add('modal__trigger');
trigger.addEventListener('click', this.open.bind(this), false);
}
}
}
function toggleScroll(scrollable) {
document.body.classList.toggle('no-scroll', !scrollable);
}
new utils.modal(document.querySelector('#modal-13')); // hashtag{modalId} scope-variable
}, false);

View File

@ -0,0 +1,80 @@
.modal {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: block;
background-color: rgba(255, 255, 255, 0.9);
min-width: 60vw;
min-height: 100px;
max-height: calc(100vh - 30px);
border-radius: 7px;
z-index: -1;
color: var(--fontbase);
padding: 20px;
overflow: auto;
&.modal--open {
z-index: 200;
}
}
@media (max-width: 999px) {
.modal {
min-width: 80vw;
}
}
@media (max-width: 666px) {
.modal {
min-width: 90vw;
}
}
@media (max-width: 444px) {
.modal {
min-width: calc(100vw - 20px);
}
}
.modal__overlay {
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
background-color: transparent;
z-index: -1;
transition: background-color .2s ease;
&.modal__overlay--open {
z-index: 199;
background-color: rgba(0, 0, 0, 0.4);
}
}
.modal__trigger {
cursor: pointer;
}
.modal__closer {
position: absolute;
top: 20px;
right: 20px;
display: flex;
align-items: center;
justify-content: center;
width: 30px;
height: 30px;
background-color: var(--darkbase);
border-radius: 2px;
cursor: pointer;
&::before {
content: '\e014';
font-family: 'Glyphicons Halflings';
color: white;
}
}
.no-scroll {
overflow: hidden;
}