Modal and Toast Setup
ДУЖЕ ВАЖЛИВО всі модалки розміщаєм в templates/blocks/modals/
В файлі init.php
повинен бути масив із всіх наявних модальних вікон
Приклад: $accepted_modal = ['modal_video','modal_contact'];
Click to open
PHP
<!-- ajax.php -->
<?php
include 'init.php';
$result = 0;
$html = '';
if (isset($_POST['modal']) && $_POST['modal'] != '') {
if (isset($_POST['dataArray'])){
$data = $_POST['dataArray'];
}
$modal_name = $_POST['modal'];
if(!isset($modal_name) || empty($modal_name)){
die(json_encode(['result' => 'error2']));
}
if(!in_array($modal_name, $accepted_modal)){
die(json_encode(['result' => 'error3']));
}
ob_start();
$tmp = 'templates/blocks/modals/'.$modal_name.'.php';
if(file_exists($tmp)){
include($tmp);
$html = ob_get_clean();
$result = 'ok';
}else{
$result = 'error4';
}
}
die(json_encode(['result' => $result, 'html' => $html]));
PHP
<!-- Modal Button -->
<a href="#" class="button" data-modals="modal_sample">Click to open</a>
<!-- dialog.php -->
<div class="dialog_wrapper">
<div class="table || main_table">
<div class="tcell || main_tcell">
<div class="dialog_bg || dialog_close"></div>
<div class="modal_ajax || dialog">
<span class="icon_close || dialog_close">
<?= svg('icon_close','') ?>
</span>
<div class="modal_content"></div>
</div>
</div>
</div>
</div>
<div id="toast">
<div class="table">
<div class="tcell">
<?= svg('icon_error','toast_icon') ?>
</div>
<div class="tcell">
<p id="toast_text">Please, enter a valid value</p>
</div>
</div>
</div>
<!-- modal_sample.php -->
<div class="image_wrap">
<?= svg('iconStars','zoomIn') ?>
</div>
<div class="modal_text">
<h3 class="modal_title">Tada</h3>
<p>Sample text</p>
</div>
<div class="modal_buttons">
<a href="#" class="button || button_success">Success</a>
<a href="#" class="button || button_danger">Danger</a>
</div>
CSS
@-webkit-keyframes fadeIn { 0%{opacity:0} 100%{opacity:1} }
@-moz-keyframes fadeIn { 0%{opacity:0} 100%{opacity:1} }
@-o-keyframes fadeIn { 0%{opacity:0} 100%{opacity:1} }
@keyframes fadeIn { 0%{opacity:0} 100%{opacity:1} }
@-webkit-keyframes showDialog { 0%{opacity:0;-webkit-transform:translateY(4rem);transform:translateY(4rem)} 100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)} }
@-moz-keyframes showDialog { 0%{opacity:0;-moz-transform:translateY(4rem);transform:translateY(4rem)} 100%{opacity:1;-moz-transform:translateY(0);transform:translateY(0)} }
@-o-keyframes showDialog { 0%{opacity:0;-o-transform:translateY(4rem);transform:translateY(4rem)} 100%{opacity:1;-o-transform:translateY(0);transform:translateY(0)} }
@keyframes showDialog { 0%{opacity:0;-webkit-transform:translateY(4rem);-moz-transform:translateY(4rem);-o-transform:translateY(4rem);transform:translateY(4rem)} 100%{opacity:1;-webkit-transform:translateY(0);-moz-transform:translateY(0);-o-transform:translateY(0);transform:translateY(0)} }
@-webkit-keyframes zoomIn { from{opacity:0;-webkit-transform:scale(0.7);transform:scale(0.7)} to{opacity:1;-webkit-transform:scale(1);transform:scale(1)} }
@-moz-keyframes zoomIn { from{opacity:0;-moz-transform:scale(0.7);transform:scale(0.7)} to{opacity:1;-moz-transform:scale(1);transform:scale(1)} }
@-o-keyframes zoomIn { from{opacity:0;-o-transform:scale(0.7);transform:scale(0.7)} to{opacity:1;-o-transform:scale(1);transform:scale(1)} }
@keyframes zoomIn { from{opacity:0;-webkit-transform:scale(0.7);-moz-transform:scale(0.7);-o-transform:scale(0.7);transform:scale(0.7)} to{opacity:1;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);transform:scale(1)} }
.dialog_wrapper{position:fixed;top:0;left:0;display:none;width:100%;height:100%;padding:4rem 0;z-index:1500}
.dialog_wrapper .main_table{width:100%;height:100%;padding-right:2rem}
.dialog_wrapper .main_tcell{padding:0 2rem}
.dialog{display:none;max-width:40rem;margin:0 auto;padding:2rem 3rem 2.5rem;-webkit-border-radius:1.5rem;-moz-border-radius:1.5rem;border-radius:1.5rem;background-color:#fff;border-top:.6rem solid #066978;z-index:1503;position:relative}
.dialog.modal_small{max-width:31rem}
.dialog.modal_medium{max-width:40rem}
.dialog.modal_large{max-width:85rem}
.dialog.modal_xlarge{max-width:65vw}
.dialog .icon_close{position:absolute;top:.5rem;right:.5rem;color:#066978;cursor:pointer;font-size:3rem;-webkit-transition:color .3s linear;-o-transition:color .3s linear;-moz-transition:color .3s linear;transition:color .3s linear}
.dialog .icon_close:focus{color:#dc3545}
.dialog .icon_close .icon{display:block}
.dialog .image_wrap{position:relative;width:7rem;height:7rem;line-height:7rem;margin:-5.5rem auto 0;-webkit-border-radius:50%;-moz-border-radius:50%;border-radius:50%;text-align:center;background-color:#066978}
.dialog .image_wrap .icon{height:4rem;width:4rem;color:#fff;-webkit-animation:zoomIn .5s both;-moz-animation:zoomIn .5s both;-o-animation:zoomIn .5s both;animation:zoomIn .5s both;-webkit-animation-delay:.2s;-moz-animation-delay:.2s;-o-animation-delay:.2s;animation-delay:.2s}
.dialog .modal_text{text-align:center;margin:2rem 0 .5rem}
.dialog .modal_text .modal_title{font-size:2.4rem;line-height:1.4;font-weight:700;color:#000;text-transform:capitalize;margin:0 auto}
.dialog .modal_text p{margin:0.5rem auto;max-width:88%}
.dialog .modal_buttons{font-size:0;text-align:center;margin:2rem auto 0;max-width:35rem}
.dialog .modal_buttons .button{width:-webkit-calc(100% / 2 - 1.4rem);width:-moz-calc(100% / 2 - 1.4rem);width:calc(100% / 2 - 1.4rem);min-width:unset;margin:.5rem .7rem}
.dialog_bg{position:fixed;left:0;top:0;display:none;width:100%;height:100%;background-color:rgba(33,33,33,0.55)}
.dialog_wrapper.visible,.dialog_bg.visible,.dialog.visible{display:block}
.dialog_opened{position:fixed;overflow-y:auto;width:100%;height:100%}
.dialog_opened .dialog_bg{-webkit-animation-name:fadeIn;-moz-animation-name:fadeIn;-o-animation-name:fadeIn;animation-name:fadeIn;-webkit-animation-duration:.3s;-moz-animation-duration:.3s;-o-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;-moz-animation-fill-mode:both;-o-animation-fill-mode:both;animation-fill-mode:both}
.dialog_opened .dialog{-webkit-animation-name:showDialog;-moz-animation-name:showDialog;-o-animation-name:showDialog;animation-name:showDialog;-webkit-animation-duration:.3s;-moz-animation-duration:.3s;-o-animation-duration:.3s;animation-duration:.3s;-webkit-animation-fill-mode:both;-moz-animation-fill-mode:both;-o-animation-fill-mode:both;animation-fill-mode:both}
.dialog_opened .dialog_wrapper{display:block}
.dialog_scrollable .dialog_wrapper{overflow-y:auto;width:-webkit-calc(100% + 4rem);width:-moz-calc(100% + 4rem);width:calc(100% + 4rem)}
.dialog_scrollable_mobile .dialog_wrapper{width:100%!important}
.dialog_scrollable_mobile .main_table{padding-right:0!important}
#toast{position:fixed;bottom:2rem;left:2rem;display:none;width:100%;max-width:28rem;padding:1rem 2rem;color:#fff;background-color:#fff;-webkit-box-shadow:.1rem .5rem 1.5rem rgba(0,0,0,0.25);-moz-box-shadow:.1rem .5rem 1.5rem rgba(0,0,0,0.25);box-shadow:.1rem .5rem 1.5rem rgba(0,0,0,0.25);-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;backface-visibility:hidden;z-index:1503}
#toast p{font-family:'Nunito Sans',sans-serif;font-size:1.4rem;color:#fff;display:block;margin:0}
#toast.error{background-color:#dc3545}
#toast.success{background-color:#28a745}
#toast .toast_icon{font-size:3rem;color:#fff;margin:0 1rem 0 0}
@media (-ms-high-contrast: none),(-ms-high-contrast: active),(-moz-touch-enabled: 0),(hover: hover) {
.dialog .icon_close:hover{color:#dc3545}
}
@media only screen and (max-width: 400px) {
.dialog .modal_buttons .button {width: 100%;margin: 0 0 1.5rem}
.dialog .modal_buttons .button:last-child {margin: 0}
}
SCSS
/* Vars */
$font: 'Nunito Sans', sans-serif;
$dark: #066978;
$success: #28a745;
$danger: #dc3545;
$white: #ffffff;
$cb: #000000;
$modalWidth: 40rem;
$modalWidthS: 31rem;
$modalWidthL: 85rem;
$modalWidthXL: 65vw;
$modalBg: $white;
$modalBorder: $dark;
$modalClose: $dark;
$modalCloseH: $danger;
$toastError: $danger;
$toastSuccess: $success;
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes showDialog {
0% {
opacity: 0;
transform: translateY(4rem);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
@keyframes zoomIn {
from {
opacity: 0;
transform: scale(0.7);
}
to {
opacity: 1;
transform: scale(1);
}
}
.dialog_wrapper {
position: fixed;
top: 0;
left: 0;
display: none;
width: 100%;
height: 100%;
padding: 4rem 0;
z-index: 1500;
.main_table {
width: 100%;
height: 100%;
padding-right: 2rem;
}
.main_tcell {
padding: 0 2rem;
}
}
.dialog {
display: none;
max-width: $modalWidth;
margin: 0 auto;
padding: 2rem 3rem 2.5rem;
border-radius: 1.5rem;
background-color: $modalBg;
border-top: 0.6rem solid $modalBorder;
z-index: 1503;
position: relative;
&.modal_small {
max-width: $modalWidthS;
}
&.modal_medium {
max-width: $modalWidth;
}
&.modal_large {
max-width: $modalWidthL;
}
&.modal_xlarge {
max-width: $modalWidthXL;
}
.icon_close {
position: absolute;
top: .5rem;
right: .5rem;
color: $modalClose;
cursor: pointer;
font-size: 3rem;
transition: color .3s linear;
&:focus {
color: $modalCloseH;
}
.icon {
display: block;
}
}
.image_wrap {
position: relative;
width: 7rem;
height: 7rem;
line-height: 7rem;
margin: -5.5rem auto 0;
border-radius: 50%;
text-align: center;
background-color: $dark;
.icon {
height: 4rem;
width: 4rem;
color: $white;
animation: zoomIn .5s both;
animation-delay: .2s;
}
}
.modal_text {
text-align: center;
margin: 2rem 0 .5rem;
.modal_title {
font-size: 2.4rem;
line-height: 1.4;
font-weight: 700;
color: $cb;
text-transform: capitalize;
margin: 0 auto;
}
p {
margin: 0.5rem auto;
max-width: 88%;
}
}
.modal_buttons {
font-size: 0;
text-align: center;
margin: 2rem auto 0;
max-width: 35rem;
.button {
width: calc(100% / 2 - 1.4rem);
min-width: unset;
margin: .5rem .7rem;
}
}
}
.dialog_bg {
position: fixed;
left: 0;
top: 0;
display: none;
width: 100%;
height: 100%;
background-color: rgba(33, 33, 33, 0.55);
}
.dialog_wrapper.visible, .dialog_bg.visible, .dialog.visible {
display: block;
}
.dialog_opened {
position: fixed;
overflow-y: auto;
width: 100%;
height: 100%;
.dialog_bg {
animation-name: fadeIn;
animation-duration: .3s;
animation-fill-mode: both;
}
.dialog {
animation-name: showDialog;
animation-duration: .3s;
animation-fill-mode: both;
}
.dialog_wrapper {
display: block;
}
}
.dialog_scrollable .dialog_wrapper {
overflow-y: auto;
width: calc(100% + 4rem)
}
.dialog_scrollable_mobile {
.dialog_wrapper {
width: 100% !important;
}
.main_table {
padding-right: 0 !important;
}
}
#toast {
position: fixed;
bottom: 2rem;
left: 2rem;
display: none;
width: 100%;
max-width: 28rem;
padding: 1rem 2rem;
color: $white;
background-color: $white;
box-shadow: .1rem .5rem 1.5rem rgba(0, 0, 0, 0.25);
backface-visibility: hidden;
z-index: 1503;
p {
font-family: $font;
font-size: 1.4rem;
color: $white;
display: block;
margin:0;
}
&.error {
background-color: $toastError;
}
&.success {
background-color: $toastSuccess;
}
.toast_icon {
font-size: 3rem;
color: $white;
margin:0 1rem 0 0;
}
}
@media (-ms-high-contrast: none),(-ms-high-contrast: active),(-moz-touch-enabled: 0),(hover: hover) {
.dialog .icon_close:hover {color: $modalCloseH}
}
@media only screen and (max-width: 400px) {
.dialog .modal_buttons .button {width: 100%;margin: 0 0 1.5rem}
.dialog .modal_buttons .button:last-child {margin: 0}
}
JavaScript
var $body = $('body'),
$window = $(window);
$.fn.dialog = function () {
var $this = $(this),
$dialogWrapper = $('.dialog_wrapper'),
$dialog = $('.dialog'),
$dialogBg = $('.dialog_bg'),
wPosSet = $window.scrollTop();
$dialogWrapper.addClass('visible');
$dialogBg.addClass('visible');
$this.addClass('visible');
$body.addClass('dialog_opened');
$body.css('top', -wPosSet + 'px');
$body.attr('data-scroll', wPosSet);
if ($this.height() > $dialogWrapper.height()) {
$body.addClass('dialog_scrollable');
} else {
$body.addClass('dialog_scrollable');
}
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
$body.addClass('dialog_scrollable_mobile');
}
$body.on('click', '.dialog_close', function () {
$dialog.removeClass('visible');
$dialogBg.removeClass('visible');
$dialogWrapper.removeClass('visible');
$body.removeClass('dialog_opened', 'dialog_scrollable_mobile');
$('.modal_ajax .modal_content').html('');
$('.dialog')
.removeClass('modal_small')
.removeClass('modal_medium')
.removeClass('modal_large')
.removeClass('modal_xlarge')
.removeClass('modal_video');
setTimeout(function () {
$window.scrollTop(wPosSet);
}, 400);
$window.scrollTop(wPosSet);
});
};
$(document).keydown(function (e) {
if (e.keyCode == 27) {
$('.dialog_close').trigger('click');
}
});
var modalArray = {},
$modalError = 0;
$body.on('click', '[data-modals]', function (e) {
e.preventDefault();
var type = $(this).data('modals');
if (typeof type == "undefined") {
$modalError++;
} else {
$modalError = 0;
switch (type) {
case 'modal_video':
var src = $(this).data('src');
if (src !== '') {
modalArray.src = src;
$modalError = 0
} else {
$modalError++;
}
break;
case 'modal_contact':
var title = $(this).data('title');
var ref = $(this).data('location-input');
if (typeof title !== "undefined" && title !== "") {
modalArray.modal_title = title;
}
if (typeof ref !== "undefined" && ref !== "") {
modalArray.locationInput = ref;
}
break;
}
}
if ($modalError === 0) {
$.ajax({
type: 'POST',
url: '/ajax.php',
dataType: 'json',
data: {
modal: type,
dataArray: modalArray
},
beforeSend: function () {
},
success: function (data) {
if (data.result == 'ok') {
$('.modal_ajax .modal_content').html(data.html);
$('.modal_ajax').dialog();
if (type == 'modal_contact') {
$('.phone_us').mask('000.000.0000');
validate_form();
}
if (type == 'modal_video') {
/*setHeight();*/
$('.dialog').addClass('modal_video');
}
}
},
error:
function () {
toast('error', "Error!");
}
});
} else {
toast('error', "Error!");
}
});
$body.on('click', '[data-modal]', function (e) {
e.preventDefault();
var data = $(this).data('modal');
var modal = $('.' + data);
$('.dialog_close').trigger('click');
modal.dialog();
});
function toast(cssClass, toastText) {
var $this = $('#toast'),
tl = new TimelineMax();
$this.attr('class', false);
$this.addClass(cssClass);
$this.find('#toast_text').html(toastText);
if (!$this.hasClass('active')) {
tl.fromTo($this, 0.3, {display: 'none', y: '100%', autoAlpha: 0}, {
display: 'block',
y: '0%',
autoAlpha: 1,
ease: Back.easeOut
}).to($this, 0.3, {
display: 'none',
y: '100%',
autoAlpha: 0,
ease: Back.easeIn,
delay: 3,
onComplete: function () {
$this.removeClass('active');
}
});
}
$this.addClass('active');
}