mirror of
https://github.com/a2nt/silverstripe-webpack.git
synced 2024-09-30 05:09:27 +02:00
Moved client side UI into an other repository
This commit is contained in:
parent
e5faa46dd3
commit
9917d7e673
17
README.md
17
README.md
@ -6,7 +6,9 @@ Checkout files at /app/ folder for details
|
|||||||
Take a look to https://github.com/a2nt/webpack-bootstrap-ui-kit.git for UI Kit details
|
Take a look to https://github.com/a2nt/webpack-bootstrap-ui-kit.git for UI Kit details
|
||||||
|
|
||||||
# UI Demo
|
# UI Demo
|
||||||
https://rawcdn.githack.com/a2nt/webpack-bootstrap-ui-kit/master/dist/index.html
|
Use UI Repository at https://github.com/a2nt/webpack-bootstrap-ui-kit.git to build static HTML files
|
||||||
|
|
||||||
|
Demo: https://rawcdn.githack.com/a2nt/webpack-bootstrap-ui-kit/master/dist/index.html
|
||||||
|
|
||||||
### Requirements:
|
### Requirements:
|
||||||
|
|
||||||
@ -21,9 +23,6 @@ git clone https://github.com/a2nt/silverstripe-webpack.git
|
|||||||
cd silverstripe-webpack
|
cd silverstripe-webpack
|
||||||
composer install
|
composer install
|
||||||
npm install
|
npm install
|
||||||
cd app
|
|
||||||
git clone https://github.com/a2nt/webpack-bootstrap-ui-kit.git ./client
|
|
||||||
cd ..
|
|
||||||
cp ./env-dist ./.env
|
cp ./env-dist ./.env
|
||||||
```
|
```
|
||||||
Those steps depends on your environment:
|
Those steps depends on your environment:
|
||||||
@ -77,27 +76,19 @@ php -d memory_limit=-1 composer.phar update --ignore-platform-reqs
|
|||||||
|
|
||||||
|
|
||||||
+ /app/client/src/js (Your JS-scripts)
|
+ /app/client/src/js (Your JS-scripts)
|
||||||
+ /app/client/src/js/_components (Your JS components to be included)
|
|
||||||
+ /app/client/src/js/_components/_spinner.js (An example to display and hide loading spinner)
|
|
||||||
+ /app/client/src/js/app.js (main application file to include website-wide components)
|
+ /app/client/src/js/app.js (main application file to include website-wide components)
|
||||||
+ /app/client/src/js/main.js (Your custom site-wide functionality)
|
+ /app/client/src/js/main.js (Your custom site-wide functionality)
|
||||||
+ /app/client/src/js/_events.js (Your custom site-wide events)
|
|
||||||
+ /app/client/src/js/_pageType_and_component_template.js (A template which can be used to create new modules)
|
+ /app/client/src/js/_pageType_and_component_template.js (A template which can be used to create new modules)
|
||||||
+ /app/client/src/types/*.js (Extra page-specific modules to be auto-compiled. My suggestion is to use *ClassName*.js and then require it at SilverStripe custom controller area)
|
+ /app/client/src/types/*.js (Extra page-specific modules to be auto-compiled. My suggestion is to use *ClassName*.js and then require it at SilverStripe custom controller area)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+ /app/clent/src/scss (Your styling to be compiled)
|
+ /app/clent/src/scss (Your styling to be compiled)
|
||||||
+ /app/clent/src/scss/_components (Your custom SCSS components)
|
|
||||||
+ /app/clent/src/scss/app.scss (main application file to include site-wide components)
|
+ /app/clent/src/scss/app.scss (main application file to include site-wide components)
|
||||||
+ /app/clent/src/scss/_variables.sccs (your custom and bootstrap variables)
|
+ /app/clent/src/scss/_variables.sccs (your custom and bootstrap variables)
|
||||||
+ /app/clent/src/scss/_layout.sccs (Your site-wide styling)
|
+ /app/clent/src/scss/_layout.sccs (Your site-wide styling)
|
||||||
|
|
||||||
|
+ /app/client/dist (Compiled frontend files js, css, images etc)
|
||||||
|
|
||||||
+ /app/client/src/index.html UI demo page
|
|
||||||
+ /app/client/src/html HTML templates to build UI demo
|
|
||||||
|
|
||||||
### Commands:
|
### Commands:
|
||||||
|
|
||||||
+ yarn - to update packages
|
+ yarn - to update packages
|
||||||
|
@ -44,11 +44,15 @@ DNADesign\ElementalUserForms\Model\ElementForm:
|
|||||||
extensions:
|
extensions:
|
||||||
- Site\Extensions\UserDefinedFormExtension
|
- Site\Extensions\UserDefinedFormExtension
|
||||||
|
|
||||||
|
|
||||||
# Blog + Widgets module extensions
|
# Blog + Widgets module extensions
|
||||||
Page:
|
Page:
|
||||||
extensions:
|
extensions:
|
||||||
- SilverStripe\Widgets\Extensions\WidgetPageExtension
|
- SilverStripe\Widgets\Extensions\WidgetPageExtension
|
||||||
|
|
||||||
|
SilverStripe\Blog\Model\Blog:
|
||||||
|
extensions:
|
||||||
|
- Site\Extensions\BlogExtension
|
||||||
SilverStripe\Blog\Model\BlogPost:
|
SilverStripe\Blog\Model\BlogPost:
|
||||||
extensions:
|
extensions:
|
||||||
- Site\Extensions\BlogPostExtension
|
- Site\Extensions\BlogPostExtension
|
||||||
|
15
app/client/dist/css/app.css
vendored
15
app/client/dist/css/app.css
vendored
File diff suppressed because one or more lines are too long
2
app/client/dist/icons/.cache
vendored
2
app/client/dist/icons/.cache
vendored
@ -1 +1 @@
|
|||||||
{"hash":"3deb17371acdc75398d81da38fad464c","version":"0.0.9","optionHash":"c067d9b2d6a96a86192ece0162f1b1ac","result":{"outputFilePrefix":"/icons/","html":["<meta name=\"mobile-web-app-capable\" content=\"yes\">","<meta name=\"theme-color\" content=\"#fff\">","<meta name=\"application-name\" content=\"Webpack App\">","<link rel=\"apple-touch-icon\" sizes=\"57x57\" href=\"app/client/dist//icons/apple-touch-icon-57x57.png\">","<link rel=\"apple-touch-icon\" sizes=\"60x60\" href=\"app/client/dist//icons/apple-touch-icon-60x60.png\">","<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"app/client/dist//icons/apple-touch-icon-72x72.png\">","<link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"app/client/dist//icons/apple-touch-icon-76x76.png\">","<link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"app/client/dist//icons/apple-touch-icon-114x114.png\">","<link rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"app/client/dist//icons/apple-touch-icon-120x120.png\">","<link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"app/client/dist//icons/apple-touch-icon-144x144.png\">","<link rel=\"apple-touch-icon\" sizes=\"152x152\" href=\"app/client/dist//icons/apple-touch-icon-152x152.png\">","<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"app/client/dist//icons/apple-touch-icon-180x180.png\">","<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">","<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">","<meta name=\"apple-mobile-web-app-title\" content=\"Webpack App\">","<link rel=\"icon\" type=\"image/png\" sizes=\"228x228\" href=\"app/client/dist//icons/coast-228x228.png\">","<meta name=\"msapplication-TileColor\" content=\"#fff\">","<meta name=\"msapplication-TileImage\" content=\"mstile-144x144.png\">","<meta name=\"msapplication-config\" content=\"browserconfig.xml\">","<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"app/client/dist//icons/favicon-32x32.png\">","<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"app/client/dist//icons/favicon-16x16.png\">","<link rel=\"shortcut icon\" href=\"app/client/dist//icons/favicon.ico\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 1)\" href=\"app/client/dist//icons/apple-touch-startup-image-320x460.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-640x920.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-640x1096.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-750x1294.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 736px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 3)\" href=\"app/client/dist//icons/apple-touch-startup-image-1182x2208.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 736px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 3)\" href=\"app/client/dist//icons/apple-touch-startup-image-1242x2148.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 1)\" href=\"app/client/dist//icons/apple-touch-startup-image-748x1024.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 1)\" href=\"app/client/dist//icons/apple-touch-startup-image-768x1004.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-1496x2048.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-1536x2008.png\">"],"files":["/icons/android-chrome-36x36.png","/icons/android-chrome-48x48.png","/icons/android-chrome-72x72.png","/icons/android-chrome-144x144.png","/icons/android-chrome-192x192.png","/icons/android-chrome-256x256.png","/icons/android-chrome-384x384.png","/icons/android-chrome-96x96.png","/icons/android-chrome-512x512.png","/icons/apple-touch-icon-57x57.png","/icons/apple-touch-icon-72x72.png","/icons/apple-touch-icon-60x60.png","/icons/apple-touch-icon-114x114.png","/icons/apple-touch-icon-120x120.png","/icons/apple-touch-icon-76x76.png","/icons/apple-touch-icon-144x144.png","/icons/apple-touch-icon-167x167.png","/icons/apple-touch-icon-152x152.png","/icons/apple-touch-icon-180x180.png","/icons/apple-touch-icon-precomposed.png","/icons/apple-touch-icon.png","/icons/coast-228x228.png","/icons/yandex-browser-50x50.png","/icons/mstile-70x70.png","/icons/mstile-144x144.png","/icons/mstile-150x150.png","/icons/mstile-310x150.png","/icons/mstile-310x310.png","/icons/favicon-16x16.png","/icons/favicon-32x32.png","/icons/favicon.ico","/icons/apple-touch-startup-image-640x920.png","/icons/apple-touch-startup-image-320x460.png","/icons/apple-touch-startup-image-640x1096.png","/icons/apple-touch-startup-image-748x1024.png","/icons/apple-touch-startup-image-750x1294.png","/icons/apple-touch-startup-image-768x1004.png","/icons/apple-touch-startup-image-1182x2208.png","/icons/apple-touch-startup-image-1242x2148.png","/icons/apple-touch-startup-image-1536x2008.png","/icons/apple-touch-startup-image-1496x2048.png","/icons/firefox_app_60x60.png","/icons/firefox_app_128x128.png","/icons/firefox_app_512x512.png","/icons/manifest.json","/icons/yandex-browser-manifest.json","/icons/browserconfig.xml","/icons/manifest.webapp"]}}
|
{"hash":"3deb17371acdc75398d81da38fad464c","version":"0.0.9","optionHash":"c067d9b2d6a96a86192ece0162f1b1ac","result":{"outputFilePrefix":"/icons/","html":["<meta name=\"mobile-web-app-capable\" content=\"yes\">","<meta name=\"theme-color\" content=\"#fff\">","<meta name=\"application-name\" content=\"Webpack App\">","<link rel=\"apple-touch-icon\" sizes=\"57x57\" href=\"app/client/dist//icons/apple-touch-icon-57x57.png\">","<link rel=\"apple-touch-icon\" sizes=\"60x60\" href=\"app/client/dist//icons/apple-touch-icon-60x60.png\">","<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"app/client/dist//icons/apple-touch-icon-72x72.png\">","<link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"app/client/dist//icons/apple-touch-icon-76x76.png\">","<link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"app/client/dist//icons/apple-touch-icon-114x114.png\">","<link rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"app/client/dist//icons/apple-touch-icon-120x120.png\">","<link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"app/client/dist//icons/apple-touch-icon-144x144.png\">","<link rel=\"apple-touch-icon\" sizes=\"152x152\" href=\"app/client/dist//icons/apple-touch-icon-152x152.png\">","<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"app/client/dist//icons/apple-touch-icon-180x180.png\">","<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">","<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">","<meta name=\"apple-mobile-web-app-title\" content=\"Webpack App\">","<link rel=\"icon\" type=\"image/png\" sizes=\"228x228\" href=\"app/client/dist//icons/coast-228x228.png\">","<meta name=\"msapplication-TileColor\" content=\"#fff\">","<meta name=\"msapplication-TileImage\" content=\"mstile-144x144.png\">","<meta name=\"msapplication-config\" content=\"browserconfig.xml\">","<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"app/client/dist//icons/favicon-32x32.png\">","<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"app/client/dist//icons/favicon-16x16.png\">","<link rel=\"shortcut icon\" href=\"app/client/dist//icons/favicon.ico\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 1)\" href=\"app/client/dist//icons/apple-touch-startup-image-320x460.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 480px) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-640x920.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-640x1096.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-750x1294.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 736px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 3)\" href=\"app/client/dist//icons/apple-touch-startup-image-1182x2208.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 414px) and (device-height: 736px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 3)\" href=\"app/client/dist//icons/apple-touch-startup-image-1242x2148.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 1)\" href=\"app/client/dist//icons/apple-touch-startup-image-748x1024.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 1)\" href=\"app/client/dist//icons/apple-touch-startup-image-768x1004.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: landscape) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-1496x2048.png\">","<link rel=\"apple-touch-startup-image\" media=\"(device-width: 768px) and (device-height: 1024px) and (orientation: portrait) and (-webkit-device-pixel-ratio: 2)\" href=\"app/client/dist//icons/apple-touch-startup-image-1536x2008.png\">"],"files":["/icons/android-chrome-36x36.png","/icons/android-chrome-48x48.png","/icons/android-chrome-72x72.png","/icons/android-chrome-96x96.png","/icons/android-chrome-144x144.png","/icons/android-chrome-192x192.png","/icons/android-chrome-256x256.png","/icons/android-chrome-384x384.png","/icons/android-chrome-512x512.png","/icons/apple-touch-icon-57x57.png","/icons/apple-touch-icon-72x72.png","/icons/apple-touch-icon-60x60.png","/icons/apple-touch-icon-76x76.png","/icons/apple-touch-icon-114x114.png","/icons/apple-touch-icon-120x120.png","/icons/apple-touch-icon-144x144.png","/icons/apple-touch-icon-167x167.png","/icons/apple-touch-icon-152x152.png","/icons/apple-touch-icon.png","/icons/apple-touch-icon-180x180.png","/icons/apple-touch-icon-precomposed.png","/icons/coast-228x228.png","/icons/yandex-browser-50x50.png","/icons/mstile-70x70.png","/icons/mstile-144x144.png","/icons/mstile-150x150.png","/icons/mstile-310x150.png","/icons/mstile-310x310.png","/icons/favicon-16x16.png","/icons/favicon-32x32.png","/icons/favicon.ico","/icons/apple-touch-startup-image-640x920.png","/icons/apple-touch-startup-image-320x460.png","/icons/apple-touch-startup-image-640x1096.png","/icons/apple-touch-startup-image-748x1024.png","/icons/apple-touch-startup-image-768x1004.png","/icons/apple-touch-startup-image-750x1294.png","/icons/apple-touch-startup-image-1182x2208.png","/icons/apple-touch-startup-image-1242x2148.png","/icons/apple-touch-startup-image-1496x2048.png","/icons/apple-touch-startup-image-1536x2008.png","/icons/firefox_app_128x128.png","/icons/firefox_app_60x60.png","/icons/firefox_app_512x512.png","/icons/manifest.json","/icons/yandex-browser-manifest.json","/icons/browserconfig.xml","/icons/manifest.webapp"]}}
|
142
app/client/dist/js/app.js
vendored
142
app/client/dist/js/app.js
vendored
File diff suppressed because one or more lines are too long
@ -1,262 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
import $ from 'jquery';
|
|
||||||
import Events from '../_events';
|
|
||||||
import Spinner from './_ui.spinner';
|
|
||||||
|
|
||||||
const AjaxUI = (($) => {
|
|
||||||
// Constants
|
|
||||||
const G = window;
|
|
||||||
const D = document;
|
|
||||||
const $Html = $('html');
|
|
||||||
const $Body = $('body');
|
|
||||||
|
|
||||||
const NAME = 'jsAjaxUI';
|
|
||||||
const DATA_KEY = NAME;
|
|
||||||
|
|
||||||
class AjaxUI {
|
|
||||||
// Constructor
|
|
||||||
constructor(element) {
|
|
||||||
this._element = element;
|
|
||||||
const $element = $(this._element);
|
|
||||||
$element.addClass(`${NAME}-active`);
|
|
||||||
|
|
||||||
$element.bind('click', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const $this = $(this);
|
|
||||||
|
|
||||||
$('.ajax').each(function() {
|
|
||||||
const $this = $(this);
|
|
||||||
$this.removeClass('active');
|
|
||||||
$this.parents('.nav-item').removeClass('active');
|
|
||||||
});
|
|
||||||
|
|
||||||
$this.addClass('loading');
|
|
||||||
|
|
||||||
AjaxUI.load($this.attr('href'), () => {
|
|
||||||
$this.removeClass('loading');
|
|
||||||
$this.parents('.nav-item').addClass('active');
|
|
||||||
$this.addClass('active');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public methods
|
|
||||||
static load(url, callback) {
|
|
||||||
// show spinner
|
|
||||||
Spinner.show(() => {
|
|
||||||
$Body.removeClass('loaded');
|
|
||||||
});
|
|
||||||
|
|
||||||
// update document location
|
|
||||||
G.MainUI.updateLocation(url);
|
|
||||||
|
|
||||||
const absoluteLocation = G.URLDetails['base'] + G.URLDetails['relative'].substring(1);
|
|
||||||
if (absoluteLocation !== G.location.href) {
|
|
||||||
G.history.pushState({
|
|
||||||
ajax: true,
|
|
||||||
page: absoluteLocation,
|
|
||||||
}, document.title, absoluteLocation);
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
sync: false,
|
|
||||||
async: true,
|
|
||||||
url,
|
|
||||||
dataType: 'json',
|
|
||||||
method: 'GET',
|
|
||||||
cache: false,
|
|
||||||
error(jqXHR) {
|
|
||||||
console.warn(`AJAX request failure: ${jqXHR.statusText}`);
|
|
||||||
G.location.href = url;
|
|
||||||
|
|
||||||
// google analytics
|
|
||||||
if (typeof G.ga === 'function') {
|
|
||||||
G.ga('send', 'event', 'error', 'AJAX ERROR', jqXHR.statusText);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
success(data, status, jqXHR) {
|
|
||||||
AjaxUI.process(data, jqXHR, callback);
|
|
||||||
|
|
||||||
// google analytics
|
|
||||||
if (typeof G.ga === 'function') {
|
|
||||||
G.ga('set', {
|
|
||||||
page: G.URLDetails['relative'] + G.URLDetails['hash'],
|
|
||||||
title: jqXHR.getResponseHeader('X-Title'),
|
|
||||||
});
|
|
||||||
G.ga('send', 'pageview');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static process(data, jqXHR, callback) {
|
|
||||||
const css = jqXHR.getResponseHeader('X-Include-CSS').split(',') || [];
|
|
||||||
const js = jqXHR.getResponseHeader('X-Include-JS').split(',') || [];
|
|
||||||
|
|
||||||
// Replace HTML regions
|
|
||||||
if (typeof(data.regions) === 'object') {
|
|
||||||
for (const key in data.regions) {
|
|
||||||
if (typeof(data.regions[key]) === 'string') {
|
|
||||||
AjaxUI.replaceRegion(data.regions[key], key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove already loaded scripts
|
|
||||||
$('link[type="text/css"]').each(function() {
|
|
||||||
const i = css.indexOf($(this).attr('href'));
|
|
||||||
if (i > -1) {
|
|
||||||
css.splice(i, 1);
|
|
||||||
} else if (!$Body.data('unload-blocked')) {
|
|
||||||
console.log(`Unloading: ${ $(this).attr('href')}`);
|
|
||||||
$(this).remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('script[type="text/javascript"]').each(function() {
|
|
||||||
const i = js.indexOf($(this).attr('src'));
|
|
||||||
if (i > -1) {
|
|
||||||
js.splice(i, 1);
|
|
||||||
} else if (!$Body.data('unload-blocked')) {
|
|
||||||
console.log(`Unloading: ${ $(this).attr('src')}`);
|
|
||||||
$(this).remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// preload CSS
|
|
||||||
this.preload(css).then(() => {
|
|
||||||
const $head = $('head');
|
|
||||||
css.forEach((el) => {
|
|
||||||
$head.append(`<link rel="stylesheet" type="text/css" href="${el}" />`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// preload JS
|
|
||||||
this.preload(js, 'script').then(() => {
|
|
||||||
|
|
||||||
js.forEach((el) => {
|
|
||||||
$Body.append(`<script type="text/javascript" charset="UTF-8" src="${el}"></script>`);
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('New page is loaded!');
|
|
||||||
|
|
||||||
// trigger events
|
|
||||||
if (typeof(data.events) === 'object') {
|
|
||||||
for (const eventName in data.events) {
|
|
||||||
$(D).trigger(eventName, [data.events[eventName]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof callback !== 'undefined') {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
|
|
||||||
$(G).trigger(Events.AJAX);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static preload(items, type = 'text', cache = true, itemCallback = false) {
|
|
||||||
if (!items.length) {
|
|
||||||
return $.Deferred().resolve().promise();
|
|
||||||
}
|
|
||||||
|
|
||||||
const dfds = [];
|
|
||||||
items.forEach((url, i) => {
|
|
||||||
const dfd = $.Deferred();
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
dataType: type,
|
|
||||||
cache,
|
|
||||||
url,
|
|
||||||
}).always(() => {
|
|
||||||
dfd.resolve();
|
|
||||||
if (itemCallback) {
|
|
||||||
itemCallback(i, url);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
dfds.push(dfd);
|
|
||||||
});
|
|
||||||
|
|
||||||
// return a master promise object which will resolve when all the deferred objects have resolved
|
|
||||||
return $.when(...dfds);
|
|
||||||
}
|
|
||||||
|
|
||||||
static replaceRegion(html, key) {
|
|
||||||
const $region = $(`[data-ajax-region="${key}"]`);
|
|
||||||
|
|
||||||
if ($region.length) {
|
|
||||||
$region.empty().append(html);
|
|
||||||
} else {
|
|
||||||
console.warn('Region returned without class or id!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dispose() {
|
|
||||||
const $element = $(this._element);
|
|
||||||
|
|
||||||
$element.removeClass(`${NAME}-active`);
|
|
||||||
$.removeData(this._element, DATA_KEY);
|
|
||||||
this._element = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static _jQueryInterface() {
|
|
||||||
return this.each(function() {
|
|
||||||
// attach functionality to element
|
|
||||||
const $element = $(this);
|
|
||||||
let data = $element.data(DATA_KEY);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
data = new AjaxUI(this);
|
|
||||||
$element.data(DATA_KEY, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jQuery interface
|
|
||||||
$.fn[NAME] = AjaxUI._jQueryInterface;
|
|
||||||
$.fn[NAME].Constructor = AjaxUI;
|
|
||||||
$.fn[NAME].noConflict = function() {
|
|
||||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
|
||||||
return AjaxUI._jQueryInterface;
|
|
||||||
};
|
|
||||||
|
|
||||||
// auto-apply
|
|
||||||
$('.ajax').ready(() => {
|
|
||||||
$('.ajax').jsAjaxUI();
|
|
||||||
});
|
|
||||||
|
|
||||||
// AJAX update browser title
|
|
||||||
$(D).on('layoutRefresh', (e, data) => {
|
|
||||||
D.title = data.Title;
|
|
||||||
|
|
||||||
$Html.attr('class', '');
|
|
||||||
if (data.ClassName) {
|
|
||||||
$Html.addClass(data.ClassName);
|
|
||||||
}
|
|
||||||
//data.Link = (data.Link === '/home/') ? '/' : data.Link;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Back/Forward functionality
|
|
||||||
G.onpopstate = function(event) {
|
|
||||||
const $existingLink = $(`a[href^="${ D.location }"]`);
|
|
||||||
|
|
||||||
if (event.state !== null && event.state.ajax) {
|
|
||||||
console.log('GOBACK (AJAX state)');
|
|
||||||
AjaxUI.load(event.state.page);
|
|
||||||
} else if ($existingLink.length && $existingLink.hasClass('ajax')) {
|
|
||||||
console.log('GOBACK (AJAX link)');
|
|
||||||
$existingLink.trigger('click');
|
|
||||||
} else {
|
|
||||||
console.log('GOBACK (HTTP)');
|
|
||||||
G.location.href = D.location;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return AjaxUI;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default AjaxUI;
|
|
@ -1,124 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
import 'hammerjs/hammer';
|
|
||||||
import 'jquery-hammerjs/jquery.hammer';
|
|
||||||
|
|
||||||
import Events from '../_events';
|
|
||||||
|
|
||||||
const CarouselUI = (($) => {
|
|
||||||
// Constants
|
|
||||||
const NAME = 'CarouselUI';
|
|
||||||
|
|
||||||
class CarouselUI {
|
|
||||||
// Static methods
|
|
||||||
|
|
||||||
static each(callback) {
|
|
||||||
$('.js-carousel').each((i, e) => {
|
|
||||||
callback(i, $(e));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static init() {
|
|
||||||
this.dispose();
|
|
||||||
|
|
||||||
this.each((i, e) => {
|
|
||||||
const $e = $(e),
|
|
||||||
id = `Carousel${i}`;
|
|
||||||
|
|
||||||
$e.attr('id', id);
|
|
||||||
$e.data('id', i);
|
|
||||||
|
|
||||||
const $items = $(e).find('.carousel-item'),
|
|
||||||
count = $items.length;
|
|
||||||
if (!count) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create carousel-controls
|
|
||||||
if ($e.data('indicators')) {
|
|
||||||
const $indicators = $('<ol class="carousel-indicators"></ol>');
|
|
||||||
$indicators.append(`<li data-target="#${ id }" data-slide-to="0" class="active"></li>`);
|
|
||||||
for (let i = 1; i < count; i++) {
|
|
||||||
$indicators.append(`<li data-target="#${ id }" data-slide-to="${ i }"></li>`);
|
|
||||||
}
|
|
||||||
$e.prepend($indicators);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create arrows
|
|
||||||
if ($e.data('arrows')) {
|
|
||||||
$e.prepend(`<i class="carousel-control-prev" data-target="#${ id }" role="button" data-slide="prev"><i class="fas fa-chevron-left" aria-hidden="true"></i><i class="sr-only">Previous</i></i>`);
|
|
||||||
$e.prepend(`<i class="carousel-control-next" data-target="#${ id }" role="button" data-slide="next"><i class="fas fa-chevron-right" aria-hidden="true"></i><i class="sr-only">Next</i></i>`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// init carousel
|
|
||||||
$e.carousel();
|
|
||||||
|
|
||||||
const $youtubeSlides = $e.find('iframe[src^="https://www.youtube.com/embed/"]');
|
|
||||||
|
|
||||||
$e.on('slide.bs.carousel', () => {
|
|
||||||
if ($youtubeSlides.length) {
|
|
||||||
$youtubeSlides.each((i, e) => {
|
|
||||||
const $e = $(e);
|
|
||||||
try {
|
|
||||||
$e.data('player', new YT.Player(e, {
|
|
||||||
events: {
|
|
||||||
'onReady': () => {
|
|
||||||
$e.data('player').pauseVideo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
$e.data('player').pauseVideo();
|
|
||||||
} catch (e) {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$e.find('.carousel-control-prev').on('click', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
$e.carousel('prev');
|
|
||||||
});
|
|
||||||
|
|
||||||
$e.find('.carousel-control-next').on('click', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
$e.carousel('next');
|
|
||||||
});
|
|
||||||
|
|
||||||
// init touch swipes
|
|
||||||
$e.hammer().bind('swipeleft', (event) => {
|
|
||||||
$(event.target).carousel('next');
|
|
||||||
});
|
|
||||||
|
|
||||||
$e.hammer().bind('swiperight', (event) => {
|
|
||||||
$(event.target).carousel('prev');
|
|
||||||
});
|
|
||||||
|
|
||||||
$e.hammer().bind('panleft', (event) => {
|
|
||||||
$(event.target).carousel('next');
|
|
||||||
});
|
|
||||||
|
|
||||||
$e.hammer().bind('panright', (event) => {
|
|
||||||
$(event.target).carousel('prev');
|
|
||||||
});
|
|
||||||
|
|
||||||
$e.find('.carousel-item').hammer().bind('tap', (event) => {
|
|
||||||
$(event.target).carousel('next');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static dispose() {
|
|
||||||
this.each((i, e) => {
|
|
||||||
$(e).carousel('dispose');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
|
||||||
CarouselUI.init();
|
|
||||||
});
|
|
||||||
|
|
||||||
return CarouselUI;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default CarouselUI;
|
|
@ -1,205 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
//import 'bootstrap-select/dist/js/bootstrap-select';
|
|
||||||
//$.fn.selectpicker.Constructor.BootstrapVersion = '4';
|
|
||||||
import 'select2/dist/js/select2.js';
|
|
||||||
|
|
||||||
import select2 from 'jquery.inputmask/dist/jquery.inputmask.bundle';
|
|
||||||
|
|
||||||
import Events from "../_events";
|
|
||||||
import SpinnerUI from './_ui.spinner';
|
|
||||||
import FormFieldUI from './_ui.form.fields';
|
|
||||||
|
|
||||||
const FormBasics = (($) => {
|
|
||||||
// Constants
|
|
||||||
const NAME = 'jsFormBasics';
|
|
||||||
const DATA_KEY = NAME;
|
|
||||||
const $Html = $('html, body');
|
|
||||||
const W = window;
|
|
||||||
const D = document;
|
|
||||||
|
|
||||||
class FormBasics {
|
|
||||||
|
|
||||||
constructor(element) {
|
|
||||||
const ui = this;
|
|
||||||
const $element = $(element);
|
|
||||||
|
|
||||||
ui._element = element;
|
|
||||||
$element.data(DATA_KEY, this);
|
|
||||||
|
|
||||||
$('[data-inputmask]').inputmask();
|
|
||||||
|
|
||||||
const $fields = $element.find(Events.FORM_FIELDS);
|
|
||||||
// init fields ui
|
|
||||||
$fields.each((i, el) => {
|
|
||||||
// skip some fields here
|
|
||||||
new FormFieldUI(el);
|
|
||||||
});
|
|
||||||
|
|
||||||
const $selectFields = $element.find('select:not([readonly])');
|
|
||||||
const $radioOptions = $element.find('input[type="radio"]');
|
|
||||||
|
|
||||||
$selectFields.each((i, el) => {
|
|
||||||
const $el = $(el);
|
|
||||||
$el.select2();
|
|
||||||
});
|
|
||||||
|
|
||||||
/*const separator = '::;::';
|
|
||||||
$selectFields.each((i, el) => {
|
|
||||||
const $el = $(el);
|
|
||||||
const maxOptions = $el.data('max-options') || false;
|
|
||||||
|
|
||||||
$el.selectpicker($.extend({
|
|
||||||
iconBase: 'fas',
|
|
||||||
tickIcon: 'fa-check',
|
|
||||||
virtualScroll: false,
|
|
||||||
dropupAuto: false,
|
|
||||||
size: 10,
|
|
||||||
maxOptions,
|
|
||||||
}, $el.data(), {
|
|
||||||
multipleSeparator: separator,
|
|
||||||
}));
|
|
||||||
|
|
||||||
// wrap options
|
|
||||||
if (maxOptions > 1) {
|
|
||||||
const wrapOptions = () => {
|
|
||||||
if (!$el.val().length) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const $container = $el.parent().find('.dropdown-toggle .filter-option');
|
|
||||||
const val = $container.text();
|
|
||||||
const vals = val.split(separator);
|
|
||||||
let html = '';
|
|
||||||
|
|
||||||
vals.forEach((opt) => {
|
|
||||||
const $opt = $el.find('option').filter((i, e) => {
|
|
||||||
return $(e).text() === opt;
|
|
||||||
});
|
|
||||||
|
|
||||||
html += `<span class="option" data-val=${ $opt.attr('value') }>${ opt
|
|
||||||
} <i class="fas fa-times btn-remove"></i></span>`;
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
$container.html(html);
|
|
||||||
|
|
||||||
// remove value
|
|
||||||
$container.find('.option').on('click', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const $opt = $(e.currentTarget);
|
|
||||||
const val = $opt.data('val').toString();
|
|
||||||
//$opt.remove();
|
|
||||||
|
|
||||||
const vals = $el.selectpicker('val');
|
|
||||||
const i = vals.indexOf(val);
|
|
||||||
if (i > -1) {
|
|
||||||
vals.splice(i, 1);
|
|
||||||
$el.selectpicker('val', vals);
|
|
||||||
}
|
|
||||||
|
|
||||||
wrapOptions();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$el.on('rendered.bs.select changed.bs.select refreshed.bs.select loaded.bs.select change', wrapOptions);
|
|
||||||
wrapOptions();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// FIX: missing conflicting 'bootstrap/js/dist/dropdown' with bootstrap-select/dist/js/bootstrap-select
|
|
||||||
$('[data-toggle="dropdown"]').on('click', (e) => {
|
|
||||||
$(e.currentTarget).siblings('.dropdown-menu').toggleClass('show');
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.dropdown-menu a').on('click', (e) => {
|
|
||||||
$(e.currentTarget).parents('.dropdown-menu').removeClass('show');
|
|
||||||
});*/
|
|
||||||
// /FIX
|
|
||||||
|
|
||||||
$fields.each((e, el) => {
|
|
||||||
const $el = $(el);
|
|
||||||
|
|
||||||
if ($el.hasClass('required') || $el.attr('aria-required')) {
|
|
||||||
$el.closest('.field').addClass('required');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$radioOptions.each((e, el) => {
|
|
||||||
const $el = $(el);
|
|
||||||
|
|
||||||
if ($el.is(':checked')) {
|
|
||||||
$el.parents('.radio').addClass('checked');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$radioOptions.on('change', (e) => {
|
|
||||||
const $el = $(e.currentTarget);
|
|
||||||
const $parent = $el.parents('.radio');
|
|
||||||
|
|
||||||
$parent.siblings('.radio').each((i, el) => {
|
|
||||||
const $el = $(el);
|
|
||||||
|
|
||||||
if (!$el.find('input').is(':checked')) {
|
|
||||||
$el.removeClass('checked');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if ($el.is(':checked')) {
|
|
||||||
$parent.addClass('checked');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$element.on('submit', (e) => {
|
|
||||||
SpinnerUI.show();
|
|
||||||
});
|
|
||||||
|
|
||||||
$element.addClass(`${NAME}-active`);
|
|
||||||
$element.trigger(Events.FORM_INIT_BASICS);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public methods
|
|
||||||
dispose() {
|
|
||||||
const $element = $(this._element);
|
|
||||||
|
|
||||||
$element.removeClass(`${NAME}-active`);
|
|
||||||
$.removeData(this._element, DATA_KEY);
|
|
||||||
this._element = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static _jQueryInterface() {
|
|
||||||
return this.each(() => {
|
|
||||||
// attach functionality to element
|
|
||||||
const $element = $(this);
|
|
||||||
let data = $element.data(DATA_KEY);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
data = new FormBasics(this);
|
|
||||||
$element.data(DATA_KEY, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jQuery interface
|
|
||||||
$.fn[NAME] = FormBasics._jQueryInterface;
|
|
||||||
$.fn[NAME].Constructor = FormBasics;
|
|
||||||
$.fn[NAME].noConflict = function() {
|
|
||||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
|
||||||
return FormBasics._jQueryInterface;
|
|
||||||
};
|
|
||||||
|
|
||||||
const init = () => {
|
|
||||||
$('form').jsFormBasics();
|
|
||||||
};
|
|
||||||
|
|
||||||
// auto-apply
|
|
||||||
$(W).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
|
||||||
init();
|
|
||||||
});
|
|
||||||
|
|
||||||
return FormBasics;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default FormBasics;
|
|
@ -1,235 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
import MainUI from "../_main";
|
|
||||||
import Events from '../_events';
|
|
||||||
import SpinnerUI from './_ui.spinner';
|
|
||||||
|
|
||||||
import 'croppie/croppie.js';
|
|
||||||
import 'exif-js/exif.js';
|
|
||||||
|
|
||||||
const CroppieUI = (($) => {
|
|
||||||
|
|
||||||
const NAME = 'jsCroppieUI';
|
|
||||||
const DATA_KEY = NAME;
|
|
||||||
|
|
||||||
const G = window;
|
|
||||||
const D = document;
|
|
||||||
|
|
||||||
const jqteOptions = {
|
|
||||||
color: false,
|
|
||||||
fsize: false,
|
|
||||||
funit: 'em',
|
|
||||||
format: false,
|
|
||||||
rule: false,
|
|
||||||
source: false,
|
|
||||||
sub: false,
|
|
||||||
sup: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
class CroppieUI {
|
|
||||||
|
|
||||||
constructor(element) {
|
|
||||||
const ui = this;
|
|
||||||
const $el = $(element);
|
|
||||||
|
|
||||||
ui.$el = $el;
|
|
||||||
$el.data(DATA_KEY, this);
|
|
||||||
|
|
||||||
ui.input = $el.find('input[type="file"]');
|
|
||||||
//ui.inputData = $('<input type="hidden" class="base64enc" name="' + ui.input.attr('name') + 'base64" />');
|
|
||||||
|
|
||||||
ui.width = ui.input.data('width');
|
|
||||||
ui.height = ui.input.data('height');
|
|
||||||
|
|
||||||
$el.append(
|
|
||||||
'<div class="cropper-wrap"><div class="cropper-container"></div>' +
|
|
||||||
'<a href="#" class="btn-remove" style="display:none"><i class="fas fa-times"></i> Remove</a></div>'
|
|
||||||
);
|
|
||||||
//$el.append(ui.inputData);
|
|
||||||
|
|
||||||
ui.uploadCropWrap = $el.find('.cropper-wrap');
|
|
||||||
ui.uploadCrop = ui.uploadCropWrap.find('.cropper-container');
|
|
||||||
|
|
||||||
const ratio = ui.width / (ui.uploadCrop.width() - 32);
|
|
||||||
ui.uploadCrop.croppie({
|
|
||||||
enableExif: true,
|
|
||||||
enforceBoundary: false,
|
|
||||||
viewport: {
|
|
||||||
width: ui.width / ratio,
|
|
||||||
height: ui.height / ratio,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.uploadCrop.hide();
|
|
||||||
|
|
||||||
ui.input.on('change', (e) => {
|
|
||||||
this.readFile(e.currentTarget);
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.$btnRemove = $el.find('.btn-remove');
|
|
||||||
ui.$btnRemove.on('click', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
ui.uploadCrop.removeClass('ready');
|
|
||||||
$el.find('.croppie-image').remove();
|
|
||||||
|
|
||||||
ui.$el.find('input[type="file"]').val('');
|
|
||||||
ui.$el.find('input[type="file"]').change();
|
|
||||||
|
|
||||||
ui.uploadCropWrap.hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ui.$el.find('img.croppie-image').length) {
|
|
||||||
ui.$btnRemove.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
readFile(input) {
|
|
||||||
const ui = this;
|
|
||||||
const $el = ui.$el;
|
|
||||||
const $form = $el.closest('form');
|
|
||||||
|
|
||||||
if (input.files && input.files[0]) {
|
|
||||||
const reader = new FileReader();
|
|
||||||
|
|
||||||
reader.onload = (e) => {
|
|
||||||
ui.uploadCrop.addClass('ready');
|
|
||||||
ui.uploadCrop.croppie('bind', {
|
|
||||||
url: e.target.result,
|
|
||||||
});
|
|
||||||
|
|
||||||
ui.uploadCrop.show();
|
|
||||||
ui.uploadCropWrap.show();
|
|
||||||
ui.$btnRemove.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.readAsDataURL(input.files[0]);
|
|
||||||
|
|
||||||
$form.on('submit', (e) => {
|
|
||||||
//$(input).val('');
|
|
||||||
SpinnerUI.show();
|
|
||||||
|
|
||||||
if (!ui.uploadCrop.hasClass('ready')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.uploadCrop.croppie('result', {
|
|
||||||
type: 'blob',
|
|
||||||
size: {
|
|
||||||
width: ui.width,
|
|
||||||
height: ui.height,
|
|
||||||
},
|
|
||||||
format: 'png',
|
|
||||||
}).then((blob) => {
|
|
||||||
const form = e.currentTarget;
|
|
||||||
const data = new FormData(form);
|
|
||||||
const name = $(input).attr('name');
|
|
||||||
|
|
||||||
data.delete('BackURL');
|
|
||||||
data.delete(name);
|
|
||||||
data.append(name, blob, `${name }-image.png`);
|
|
||||||
data.append('ajax', '1');
|
|
||||||
|
|
||||||
if (!$(form).data('jsFormValidate').validate()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: $(form).attr('action'),
|
|
||||||
data,
|
|
||||||
processData: false,
|
|
||||||
contentType: false,
|
|
||||||
type: $(form).attr('method'),
|
|
||||||
success: function(data) {
|
|
||||||
let IS_JSON = false;
|
|
||||||
let json = {};
|
|
||||||
try {
|
|
||||||
IS_JSON = true;
|
|
||||||
json = $.parseJSON(data);
|
|
||||||
} catch (e) {
|
|
||||||
IS_JSON = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IS_JSON) {
|
|
||||||
/*for (let k in json) {
|
|
||||||
$form.find('select[name="' + k + '"],input[name="' + k + '"],textarea[name="' + k + '"]').setError(true, json[k]);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (typeof json['status'] !== 'undefined') {
|
|
||||||
if (json['status'] === 'success') {
|
|
||||||
MainUI.alert(json['message'], json['status']);
|
|
||||||
|
|
||||||
if (typeof json['link'] !== 'undefined') {
|
|
||||||
setTimeout(() => {
|
|
||||||
G.location = json['link'];
|
|
||||||
}, 2000);
|
|
||||||
} else {
|
|
||||||
//G.location.reload(false);
|
|
||||||
}
|
|
||||||
} else if (json['status'] === 'error') {
|
|
||||||
MainUI.alert(json['message'], json['status']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof json['form'] !== 'undefined') {
|
|
||||||
$(form).replaceWith(json['form']);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$(form).replaceWith(data);
|
|
||||||
//G.location.reload(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
SpinnerUI.hide();
|
|
||||||
$(G).trigger(Events.AJAX);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
//ui.inputData.val(data);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
console.log('Sorry - your browser doesn\'t support the FileReader API');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static dispose() {
|
|
||||||
console.log(`Destroying: ${NAME}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
static _jQueryInterface() {
|
|
||||||
return this.each((i, el) => {
|
|
||||||
// attach functionality to element
|
|
||||||
const $el = $(el);
|
|
||||||
let data = $el.data(DATA_KEY);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
data = new CroppieUI(el);
|
|
||||||
$el.data(DATA_KEY, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jQuery interface
|
|
||||||
$.fn[NAME] = CroppieUI._jQueryInterface;
|
|
||||||
$.fn[NAME].Constructor = CroppieUI;
|
|
||||||
$.fn[NAME].noConflict = () => {
|
|
||||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
|
||||||
return CroppieUI._jQueryInterface;
|
|
||||||
};
|
|
||||||
|
|
||||||
// auto-apply
|
|
||||||
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
|
||||||
$('.field.croppie').jsCroppieUI();
|
|
||||||
});
|
|
||||||
|
|
||||||
return CroppieUI;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default CroppieUI;
|
|
@ -1,107 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
import Events from '../_events';
|
|
||||||
|
|
||||||
import 'bootstrap-datepicker/dist/js/bootstrap-datepicker.js';
|
|
||||||
import 'bootstrap-timepicker/js/bootstrap-timepicker.js';
|
|
||||||
|
|
||||||
const DatetimeUI = (($) => {
|
|
||||||
// Constants
|
|
||||||
const W = window;
|
|
||||||
const D = document;
|
|
||||||
const $Body = $('body');
|
|
||||||
|
|
||||||
const NAME = 'jsDatetimeUI';
|
|
||||||
const DATA_KEY = NAME;
|
|
||||||
|
|
||||||
const datepickerOptions = {
|
|
||||||
autoclose: true,
|
|
||||||
startDate: 0,
|
|
||||||
//todayBtn: true,
|
|
||||||
todayHighlight: true,
|
|
||||||
clearBtn: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
class DatetimeUI {
|
|
||||||
constructor(el) {
|
|
||||||
const ui = this;
|
|
||||||
const $el = $(el);
|
|
||||||
|
|
||||||
ui._el = el;
|
|
||||||
|
|
||||||
// datepicker
|
|
||||||
if ($el.hasClass('date') || $el.attr('type') === 'date') {
|
|
||||||
const defaultDate = ($el.attr('name').toLowerCase().indexOf('end') !== -1) ?
|
|
||||||
'+4d' :
|
|
||||||
'+3d';
|
|
||||||
|
|
||||||
$el.attr('readonly', 'true');
|
|
||||||
$el.datepicker($.extend(datepickerOptions, {
|
|
||||||
defaultViewDate: defaultDate,
|
|
||||||
multidate: $el.data('multidate'),
|
|
||||||
}, $el.data()));
|
|
||||||
} else
|
|
||||||
|
|
||||||
// timepicker
|
|
||||||
if ($el.hasClass('time') || $el.attr('type') === 'time') {
|
|
||||||
$el.attr('readonly', 'true');
|
|
||||||
$el.timepicker($.extend({
|
|
||||||
snapToStep: true,
|
|
||||||
icons: {
|
|
||||||
up: 'fas fa-chevron-up',
|
|
||||||
down: 'fas fa-chevron-down',
|
|
||||||
},
|
|
||||||
}, $el.data())).on('show.timepicker', (e) => {
|
|
||||||
const $el = $(e.currentTarget);
|
|
||||||
const $dropdown = $Body.find('.bootstrap-timepicker-widget');
|
|
||||||
|
|
||||||
if (!$dropdown.find('[data-action="clear"]').length) {
|
|
||||||
$dropdown.find('tbody').append('<tr><td colspan="5"><a href="#" data-action="clear">Clear</a></td></tr>');
|
|
||||||
}
|
|
||||||
|
|
||||||
const $clearBtn = $dropdown.find('[data-action="clear"]');
|
|
||||||
$clearBtn.on('click', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
$el.timepicker('clear');
|
|
||||||
$el.timepicker('hideWidget');
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static dispose() {
|
|
||||||
console.log(`Destroying: ${NAME}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
static _jQueryInterface() {
|
|
||||||
return this.each(function() {
|
|
||||||
// attach functionality to element
|
|
||||||
const $el = $(this);
|
|
||||||
let data = $el.data(DATA_KEY);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
data = new DatetimeUI(this);
|
|
||||||
$el.data(DATA_KEY, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jQuery interface
|
|
||||||
$.fn[NAME] = DatetimeUI._jQueryInterface;
|
|
||||||
$.fn[NAME].Constructor = DatetimeUI;
|
|
||||||
$.fn[NAME].noConflict = function() {
|
|
||||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
|
||||||
return DatetimeUI._jQueryInterface;
|
|
||||||
};
|
|
||||||
|
|
||||||
// auto-apply
|
|
||||||
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
|
||||||
$('input.date, input.time,input[type="date"], input[type="time"]').jsDatetimeUI();
|
|
||||||
});
|
|
||||||
|
|
||||||
return DatetimeUI;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default DatetimeUI;
|
|
@ -1,80 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
import Events from '../_events';
|
|
||||||
import Spinner from '../_components/_ui.spinner';
|
|
||||||
import FormValidateField from "./_ui.form.validate.field";
|
|
||||||
|
|
||||||
import '../../thirdparty/jquery-te/jquery-te.js';
|
|
||||||
|
|
||||||
const JqteUI = (($) => {
|
|
||||||
|
|
||||||
const NAME = 'jsJqteUI';
|
|
||||||
const DATA_KEY = NAME;
|
|
||||||
|
|
||||||
const jqteOptions = {
|
|
||||||
color: false,
|
|
||||||
fsize: false,
|
|
||||||
funit: 'em',
|
|
||||||
format: false,
|
|
||||||
rule: false,
|
|
||||||
source: false,
|
|
||||||
sub: false,
|
|
||||||
sup: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
class JqteUI {
|
|
||||||
|
|
||||||
constructor(element) {
|
|
||||||
const ui = this;
|
|
||||||
const $element = $(element);
|
|
||||||
const validationUI = $element.data('jsFormValidateField');
|
|
||||||
|
|
||||||
ui._element = element;
|
|
||||||
$element.data(DATA_KEY, this);
|
|
||||||
$element.jqte(jqteOptions);
|
|
||||||
|
|
||||||
// dynamic error control
|
|
||||||
if (validationUI) {
|
|
||||||
$element.parents('.jqte').find('.jqte_editor').on('change', (e) => {
|
|
||||||
validationUI.validate();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static dispose() {
|
|
||||||
console.log(`Destroying: ${NAME}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
static _jQueryInterface() {
|
|
||||||
return this.each(function() {
|
|
||||||
// attach functionality to element
|
|
||||||
const $element = $(this);
|
|
||||||
let data = $element.data(DATA_KEY);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
data = new JqteUI(this);
|
|
||||||
$element.data(DATA_KEY, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jQuery interface
|
|
||||||
$.fn[NAME] = JqteUI._jQueryInterface;
|
|
||||||
$.fn[NAME].Constructor = JqteUI;
|
|
||||||
$.fn[NAME].noConflict = function() {
|
|
||||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
|
||||||
return JqteUI._jQueryInterface;
|
|
||||||
};
|
|
||||||
|
|
||||||
// auto-apply
|
|
||||||
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
|
||||||
$('textarea.jqte-field').jsJqteUI();
|
|
||||||
});
|
|
||||||
|
|
||||||
return JqteUI;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default JqteUI;
|
|
@ -1,203 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
import Events from '../_events';
|
|
||||||
import LANG from '../lang/_en';
|
|
||||||
import FormValidateField from "./_ui.form.validate.field";
|
|
||||||
|
|
||||||
const SteppedForm = (($) => {
|
|
||||||
// Constants
|
|
||||||
const NAME = 'jsSteppedForm';
|
|
||||||
const DATA_KEY = NAME;
|
|
||||||
|
|
||||||
class SteppedForm {
|
|
||||||
|
|
||||||
constructor(element) {
|
|
||||||
const ui = this;
|
|
||||||
const $element = $(element);
|
|
||||||
|
|
||||||
$element.data(DATA_KEY, this);
|
|
||||||
|
|
||||||
if (!$element.find('.steps-counter').length) {
|
|
||||||
$element.prepend(LANG['en'][NAME]['STEPCOUNTER']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$element.find('.steps-buttons').length) {
|
|
||||||
$element.append(LANG['en'][NAME]['STEPBUTTONS']);
|
|
||||||
}
|
|
||||||
|
|
||||||
ui._currentStepCounter = $element.find('.steps-counter .current-step');
|
|
||||||
ui._totalStepsCounter = $element.find('.steps-counter .total-steps');
|
|
||||||
|
|
||||||
ui._steps = $element.find('.step');
|
|
||||||
ui._stepNext = $element.find('.step-next');
|
|
||||||
|
|
||||||
ui._stepPrev = $element.find('.step-prev');
|
|
||||||
ui._actions = $element.children('.btn-toolbar,.form-actions');
|
|
||||||
|
|
||||||
ui._element = element;
|
|
||||||
ui._currentStep = 1;
|
|
||||||
ui._totalSteps = ui._steps.last().data('step') || ui._steps.length;
|
|
||||||
ui._stepsOrder = [];
|
|
||||||
|
|
||||||
ui._totalStepsCounter.text(ui._totalSteps);
|
|
||||||
|
|
||||||
// check if one of the steps already has an error
|
|
||||||
const $hasError = ui._steps
|
|
||||||
.find('.field.error,.field.holder-error,.field.holder-validation,.field.holder-info,.field.holder-warning,.field.holder-good')
|
|
||||||
.first();
|
|
||||||
if ($hasError.length) {
|
|
||||||
const $modal = $element.parents('.modal');
|
|
||||||
|
|
||||||
// show modal
|
|
||||||
if ($modal.length && typeof $modal.modal !== 'undefined') {
|
|
||||||
$modal.modal('show');
|
|
||||||
}
|
|
||||||
|
|
||||||
ui._currentStep = $hasError.parents('.step').data('step') || ui._currentStep;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
|
|
||||||
ui.step(`.step[data-step="${ ui._currentStep }"]`);
|
|
||||||
|
|
||||||
ui._stepNext.on('click', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
ui.next();
|
|
||||||
});
|
|
||||||
|
|
||||||
ui._stepPrev.on('click', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
ui.prev();
|
|
||||||
});
|
|
||||||
|
|
||||||
$element.find('.step-toggle').on('click', (e) => {
|
|
||||||
const $el = $(e.currentTarget);
|
|
||||||
|
|
||||||
e.preventDefault();
|
|
||||||
ui.step($el.data('target'));
|
|
||||||
});
|
|
||||||
|
|
||||||
$element.addClass(`${NAME}-active`);
|
|
||||||
$element.trigger(Events.FORM_INIT_STEPPED);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public methods
|
|
||||||
dispose() {
|
|
||||||
const ui = this;
|
|
||||||
const $element = $(ui._element);
|
|
||||||
|
|
||||||
$element.removeClass(`${NAME}-active`);
|
|
||||||
$.removeData(ui._element, DATA_KEY);
|
|
||||||
ui._element = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
next() {
|
|
||||||
const ui = this;
|
|
||||||
|
|
||||||
if (ui._currentStep >= ui._totalSteps) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.step(`.step[data-step="${ ui._currentStep + 1 }"]`);
|
|
||||||
}
|
|
||||||
|
|
||||||
prev() {
|
|
||||||
const ui = this;
|
|
||||||
|
|
||||||
if (ui._currentStep <= 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.step(ui._stepsOrder[ui._currentStep - 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
step(target) {
|
|
||||||
const ui = this;
|
|
||||||
const $element = $(ui._element);
|
|
||||||
const $target = $element.find(target);
|
|
||||||
const targetStep = parseInt($target.data('step'));
|
|
||||||
|
|
||||||
// validate current step
|
|
||||||
let valid = true;
|
|
||||||
|
|
||||||
if (targetStep > ui._currentStep) {
|
|
||||||
ui.currentStep().find('input,textarea,select').each((i, el) => {
|
|
||||||
const $el = $(el);
|
|
||||||
const fieldUI = $el.data('jsFormValidateField');
|
|
||||||
|
|
||||||
if (fieldUI && !fieldUI.validate()) {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
|
|
||||||
if (parseInt($target.data('step')) <= '1') {
|
|
||||||
ui._stepPrev.hide();
|
|
||||||
$element.trigger(Events.FORM_STEPPED_FIRST_STEP);
|
|
||||||
} else {
|
|
||||||
ui._stepPrev.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseInt($target.data('step')) >= ui._totalSteps) {
|
|
||||||
ui._stepNext.hide();
|
|
||||||
ui._actions.show();
|
|
||||||
|
|
||||||
$element.trigger(Events.FORM_STEPPED_LAST_STEP);
|
|
||||||
} else {
|
|
||||||
ui._stepNext.show();
|
|
||||||
ui._actions.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
ui._currentStep = targetStep;
|
|
||||||
ui._stepsOrder[ui._currentStep] = $target;
|
|
||||||
|
|
||||||
ui._steps.removeClass('active');
|
|
||||||
$target.addClass('active');
|
|
||||||
|
|
||||||
ui._currentStepCounter.text(ui._currentStep);
|
|
||||||
|
|
||||||
$target.trigger(Events.FORM_STEPPED_NEW_STEP);
|
|
||||||
$element.trigger(Events.FORM_STEPPED_NEW_STEP);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentStep() {
|
|
||||||
const ui = this;
|
|
||||||
const $element = $(ui._element);
|
|
||||||
|
|
||||||
return $element.find('.step.active');
|
|
||||||
}
|
|
||||||
|
|
||||||
static _jQueryInterface() {
|
|
||||||
return this.each(function() {
|
|
||||||
// attach functionality to element
|
|
||||||
const $element = $(this);
|
|
||||||
let data = $element.data(DATA_KEY);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
data = new SteppedForm(this);
|
|
||||||
$element.data(DATA_KEY, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jQuery interface
|
|
||||||
$.fn[NAME] = SteppedForm._jQueryInterface;
|
|
||||||
$.fn[NAME].Constructor = SteppedForm;
|
|
||||||
$.fn[NAME].noConflict = function() {
|
|
||||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
|
||||||
return SteppedForm._jQueryInterface;
|
|
||||||
};
|
|
||||||
|
|
||||||
// auto-apply
|
|
||||||
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
|
||||||
$('.form-stepped').jsSteppedForm();
|
|
||||||
});
|
|
||||||
|
|
||||||
return SteppedForm;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default SteppedForm;
|
|
@ -1,148 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
import Events from "../_events";
|
|
||||||
|
|
||||||
const FormStorage = (($) => {
|
|
||||||
// Constants
|
|
||||||
const NAME = 'jsFormStorage';
|
|
||||||
const DATA_KEY = NAME;
|
|
||||||
const STORAGE = window.localStorage;
|
|
||||||
|
|
||||||
class FormStorage {
|
|
||||||
|
|
||||||
constructor(element) {
|
|
||||||
const ui = this;
|
|
||||||
const $element = $(element);
|
|
||||||
const $elements = $element.find('input, textarea, select');
|
|
||||||
|
|
||||||
const setRangeValues = function(el) {
|
|
||||||
const $el = $(el);
|
|
||||||
$el.siblings('.value').text($el.val());
|
|
||||||
};
|
|
||||||
|
|
||||||
ui._element = element;
|
|
||||||
$element.data(DATA_KEY, this);
|
|
||||||
|
|
||||||
$element.addClass(`${NAME}-active`);
|
|
||||||
|
|
||||||
// restore form data from localStorage
|
|
||||||
$elements.each((i, el) => {
|
|
||||||
const $el = $(el);
|
|
||||||
const id = $el.attr('id');
|
|
||||||
const type = $el.attr('type');
|
|
||||||
const val = STORAGE.getItem(NAME + id);
|
|
||||||
|
|
||||||
if (type === 'file') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id && val && type) {
|
|
||||||
if (type && (type === 'checkbox' || type === 'radio')) {
|
|
||||||
$el.prop('checked', val);
|
|
||||||
} else {
|
|
||||||
$el.val(val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$el.trigger(Events.RESTORE_FIELD);
|
|
||||||
});
|
|
||||||
|
|
||||||
// range fields
|
|
||||||
$('input[type="range"]').each((i, el) => {
|
|
||||||
setRangeValues(el);
|
|
||||||
});
|
|
||||||
|
|
||||||
$element.trigger(Events.RESTORE_FIELD);
|
|
||||||
|
|
||||||
$('input[type="range"]').on('change', (e) => {
|
|
||||||
setRangeValues(e.currentTarget);
|
|
||||||
});
|
|
||||||
|
|
||||||
// store form data into localStorage
|
|
||||||
$elements.on('change', (e) => {
|
|
||||||
const $el = $(e.currentTarget);
|
|
||||||
const id = $el.attr('id');
|
|
||||||
const type = $el.attr('type');
|
|
||||||
|
|
||||||
// skip some elements
|
|
||||||
if ($el.hasClass('no-storage')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let val = $el.val();
|
|
||||||
|
|
||||||
if (type && (type === 'checkbox' || type === 'radio')) {
|
|
||||||
val = !!$el.is(':checked');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id && type && type !== 'password') {
|
|
||||||
STORAGE.setItem(NAME + id, val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$element.on('submit', () => {
|
|
||||||
$element.data(DATA_KEY).clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
$element.find('.btn-toolbar,.form-actions').children('button,[type="submit"],[type="clear"]').on('click', () => {
|
|
||||||
$element.data(DATA_KEY).clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
$element.addClass(`${NAME}-active`);
|
|
||||||
$element.trigger(Events.FORM_INIT_STORAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public methods
|
|
||||||
dispose() {
|
|
||||||
const $element = $(this._element);
|
|
||||||
|
|
||||||
$element.removeClass(`${NAME}-active`);
|
|
||||||
$.removeData(this._element, DATA_KEY);
|
|
||||||
this._element = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
clear() {
|
|
||||||
STORAGE.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
static _jQueryInterface() {
|
|
||||||
if (typeof window.localStorage !== 'undefined') {
|
|
||||||
return this.each(function() {
|
|
||||||
// attach functionality to element
|
|
||||||
const $element = $(this);
|
|
||||||
let data = $element.data(DATA_KEY);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
data = new FormStorage(this);
|
|
||||||
$element.data(DATA_KEY, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jQuery interface
|
|
||||||
$.fn[NAME] = FormStorage._jQueryInterface;
|
|
||||||
$.fn[NAME].Constructor = FormStorage;
|
|
||||||
$.fn[NAME].noConflict = function() {
|
|
||||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
|
||||||
return FormStorage._jQueryInterface;
|
|
||||||
};
|
|
||||||
|
|
||||||
// auto-apply
|
|
||||||
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
|
||||||
$('form').each((i, el) => {
|
|
||||||
const $el = $(el);
|
|
||||||
|
|
||||||
// skip some forms
|
|
||||||
if ($el.hasClass('no-storage')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$el.jsFormStorage();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return FormStorage;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default FormStorage;
|
|
@ -1,150 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
import Events from "../_events";
|
|
||||||
|
|
||||||
const FormValidateField = (($) => {
|
|
||||||
// Constants
|
|
||||||
const NAME = 'jsFormValidateField';
|
|
||||||
const DATA_KEY = NAME;
|
|
||||||
const $Html = $('html, body');
|
|
||||||
|
|
||||||
class FormValidateField {
|
|
||||||
|
|
||||||
constructor(element) {
|
|
||||||
const ui = this;
|
|
||||||
const $element = $(element);
|
|
||||||
|
|
||||||
ui._element = element;
|
|
||||||
ui._actions = $element.parents('form').children('.btn-toolbar,.form-actions');
|
|
||||||
$element.data(DATA_KEY, this);
|
|
||||||
|
|
||||||
// prevent browsers checks (will do it using JS)
|
|
||||||
$element.attr('novalidate', 'novalidate');
|
|
||||||
|
|
||||||
$element.on('change focusout', (e) => {
|
|
||||||
ui.validate(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
$element.addClass(`${NAME}-active`);
|
|
||||||
$element.trigger(Events.FORM_INIT_VALIDATE_FIELD);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public methods
|
|
||||||
dispose() {
|
|
||||||
const $element = $(this._element);
|
|
||||||
|
|
||||||
$element.removeClass(`${NAME}-active`);
|
|
||||||
$.removeData(this._element, DATA_KEY);
|
|
||||||
this._element = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
validate(scrollTo = true) {
|
|
||||||
const ui = this;
|
|
||||||
const $el = $(ui._element);
|
|
||||||
const $field = $el.closest('.field');
|
|
||||||
const extraChecks = $el.data(`${NAME}-extra`);
|
|
||||||
let valid = true;
|
|
||||||
let msg = null;
|
|
||||||
|
|
||||||
const val = $el.val();
|
|
||||||
|
|
||||||
// browser checks + required
|
|
||||||
if (!ui._element.checkValidity() ||
|
|
||||||
($el.hasClass('required') && (!val.length || !val.trim().length ||
|
|
||||||
ui.isHtml(val) && !$(val).text().length
|
|
||||||
))
|
|
||||||
) {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// validate URL
|
|
||||||
if ($el.hasClass('url') && val.length && !this.valideURL(val)) {
|
|
||||||
valid = false;
|
|
||||||
msg = 'URL must start with http:// or https://. For example: https://your-domain.com/';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.removeError();
|
|
||||||
|
|
||||||
// extra checks
|
|
||||||
if (extraChecks) {
|
|
||||||
extraChecks.forEach((check) => {
|
|
||||||
valid = valid && check();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (valid) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setError(scrollTo, msg);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
isHtml(str) {
|
|
||||||
const doc = new DOMParser().parseFromString(str, "text/html");
|
|
||||||
return Array.from(doc.body.childNodes).some((node) => node.nodeType === 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
valideURL(str) {
|
|
||||||
const pattern = new RegExp('^(https?:\\/\\/){1}' + // protocol
|
|
||||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' + // domain name
|
|
||||||
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
|
|
||||||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
|
|
||||||
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
|
|
||||||
'(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator
|
|
||||||
return pattern.test(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
setError(scrollTo = true, msg = null) {
|
|
||||||
const ui = this;
|
|
||||||
const $field = $(ui._element).closest('.field');
|
|
||||||
const pos = $field.offset().top;
|
|
||||||
|
|
||||||
$field.addClass('error');
|
|
||||||
if (msg) {
|
|
||||||
$field.append(`<div class="message alert alert-error alert-danger">${ msg }</div>`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scrollTo) {
|
|
||||||
$field.focus();
|
|
||||||
$Html.scrollTop(pos - 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
removeError() {
|
|
||||||
const ui = this;
|
|
||||||
const $field = $(ui._element).closest('.field');
|
|
||||||
|
|
||||||
$field.removeClass('error');
|
|
||||||
|
|
||||||
$field.removeClass('holder-error');
|
|
||||||
$field.removeClass('holder-validation');
|
|
||||||
$field.find('.message').remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
static _jQueryInterface() {
|
|
||||||
return this.each(function() {
|
|
||||||
// attach functionality to element
|
|
||||||
const $element = $(this);
|
|
||||||
let data = $element.data(DATA_KEY);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
data = new FormValidateField(this);
|
|
||||||
$element.data(DATA_KEY, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jQuery interface
|
|
||||||
$.fn[NAME] = FormValidateField._jQueryInterface;
|
|
||||||
$.fn[NAME].Constructor = FormValidateField;
|
|
||||||
$.fn[NAME].noConflict = function() {
|
|
||||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
|
||||||
return FormValidateField._jQueryInterface;
|
|
||||||
};
|
|
||||||
|
|
||||||
return FormValidateField;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default FormValidateField;
|
|
@ -1,138 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
import Events from "../_events";
|
|
||||||
import FormValidateField from "./_ui.form.validate.field";
|
|
||||||
import SpinnerUI from './_ui.spinner';
|
|
||||||
|
|
||||||
const FormValidate = (($) => {
|
|
||||||
// Constants
|
|
||||||
const NAME = 'jsFormValidate';
|
|
||||||
const DATA_KEY = NAME;
|
|
||||||
const $Html = $('html, body');
|
|
||||||
|
|
||||||
class FormValidate {
|
|
||||||
|
|
||||||
constructor(element) {
|
|
||||||
const ui = this;
|
|
||||||
const $element = $(element);
|
|
||||||
const $fields = $element.find('input,textarea,select');
|
|
||||||
|
|
||||||
ui._element = element;
|
|
||||||
$element.data(DATA_KEY, this);
|
|
||||||
|
|
||||||
ui._fields = $fields;
|
|
||||||
ui._stepped_form = $element.data('jsSteppedForm');
|
|
||||||
|
|
||||||
// prevent browsers checks (will do it using JS)
|
|
||||||
$element.attr('novalidate', 'novalidate');
|
|
||||||
|
|
||||||
$element.on(Events.FORM_INIT_STEPPED, () => {
|
|
||||||
ui._stepped_form = $element.data('jsSteppedForm');
|
|
||||||
});
|
|
||||||
|
|
||||||
// init fields validation
|
|
||||||
$fields.each((i, el) => {
|
|
||||||
// skip some fields here
|
|
||||||
if ($(el).attr('role') === 'combobox') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new FormValidateField(el);
|
|
||||||
});
|
|
||||||
|
|
||||||
// check form
|
|
||||||
$element.on('submit', (e) => {
|
|
||||||
ui.validate(true, () => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
// switch to step
|
|
||||||
if (ui._stepped_form) {
|
|
||||||
const $el = $element.find('.error').first();
|
|
||||||
|
|
||||||
if ($el.length) {
|
|
||||||
ui._stepped_form.step($el.parents('.step'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$element.trigger(Events.FORM_VALIDATION_FAILED);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$element.addClass(`${NAME}-active`);
|
|
||||||
$element.trigger(Events.FORM_INIT_VALIDATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public methods
|
|
||||||
dispose() {
|
|
||||||
const $element = $(this._element);
|
|
||||||
|
|
||||||
$element.removeClass(`${NAME}-active`);
|
|
||||||
$.removeData(this._element, DATA_KEY);
|
|
||||||
this._element = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
validate(scrollTo = true, badCallback = false) {
|
|
||||||
console.log('Checking the form ...');
|
|
||||||
const ui = this;
|
|
||||||
let valid = true;
|
|
||||||
|
|
||||||
ui._fields.each((i, el) => {
|
|
||||||
const $el = $(el);
|
|
||||||
const fieldUI = $el.data('jsFormValidateField');
|
|
||||||
|
|
||||||
if (fieldUI && !fieldUI.validate()) {
|
|
||||||
if (badCallback) {
|
|
||||||
badCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Invalid form data:');
|
|
||||||
console.log($el);
|
|
||||||
|
|
||||||
SpinnerUI.hide();
|
|
||||||
valid = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static _jQueryInterface() {
|
|
||||||
return this.each(function() {
|
|
||||||
// attach functionality to element
|
|
||||||
const $element = $(this);
|
|
||||||
let data = $element.data(DATA_KEY);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
data = new FormValidate(this);
|
|
||||||
$element.data(DATA_KEY, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jQuery interface
|
|
||||||
$.fn[NAME] = FormValidate._jQueryInterface;
|
|
||||||
$.fn[NAME].Constructor = FormValidate;
|
|
||||||
$.fn[NAME].noConflict = function() {
|
|
||||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
|
||||||
return FormValidate._jQueryInterface;
|
|
||||||
};
|
|
||||||
|
|
||||||
// auto-apply
|
|
||||||
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
|
||||||
$('form').each((i, el) => {
|
|
||||||
const $el = $(el);
|
|
||||||
|
|
||||||
// skip some forms
|
|
||||||
if ($el.hasClass('no-validation')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$el.jsFormValidate();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return FormValidate;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default FormValidate;
|
|
@ -1,266 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
import $ from 'jquery';
|
|
||||||
import Events from '../_events';
|
|
||||||
import mapBoxGL from 'mapbox-gl';
|
|
||||||
//import "./mapStorage";
|
|
||||||
|
|
||||||
import '../../scss/_components/_ui.map.scss';
|
|
||||||
|
|
||||||
const W = window;
|
|
||||||
|
|
||||||
const MapAPI = (($) => {
|
|
||||||
const STORAGE = W.localStorage;
|
|
||||||
|
|
||||||
// Constants
|
|
||||||
const NAME = 'jsMapAPI';
|
|
||||||
const DATA_KEY = NAME;
|
|
||||||
const $BODY = $('body');
|
|
||||||
let Map;
|
|
||||||
let currentStyle;
|
|
||||||
|
|
||||||
class MapAPI {
|
|
||||||
// Constructor
|
|
||||||
constructor(el) {
|
|
||||||
this._el = el;
|
|
||||||
const $el = $(this._el);
|
|
||||||
const config = $el.data();
|
|
||||||
|
|
||||||
const center = [
|
|
||||||
(config['lng'] ? config['lng'] : $BODY.data('default-lng')),
|
|
||||||
(config['lat'] ? config['lat'] : $BODY.data('default-lat')),
|
|
||||||
];
|
|
||||||
const popup = new mapBoxGL.Popup({
|
|
||||||
closeOnClick: false,
|
|
||||||
className: 'popup',
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
currentStyle = this.getStyle();
|
|
||||||
mapBoxGL.accessToken = $el.data('key');
|
|
||||||
Map = new mapBoxGL.Map({
|
|
||||||
'container': $el.find('.mapAPI-map')[0],
|
|
||||||
'center': center,
|
|
||||||
//hash: true,
|
|
||||||
'style': currentStyle,
|
|
||||||
'localIdeographFontFamily': $BODY.css('font-family'),
|
|
||||||
'zoom': (config['mapZoom'] ? config['mapZoom'] : 10),
|
|
||||||
'attributionControl': false,
|
|
||||||
'antialias': true,
|
|
||||||
/*'pitch': 45,
|
|
||||||
'bearing': -17.6*/
|
|
||||||
|
|
||||||
/*transformRequest: (url, resourceType)=> {
|
|
||||||
if(resourceType === 'Source' && url.startsWith('http://myHost')) {
|
|
||||||
return {
|
|
||||||
url: url.replace('http', 'https'),
|
|
||||||
headers: { 'my-custom-header': true},
|
|
||||||
credentials: 'include' // Include cookies for cross-origin requests
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
})
|
|
||||||
.addControl(new mapBoxGL.AttributionControl({
|
|
||||||
compact: true,
|
|
||||||
}))
|
|
||||||
.addControl(new mapBoxGL.NavigationControl(), 'top-right')
|
|
||||||
.addControl(new mapBoxGL.GeolocateControl({
|
|
||||||
positionOptions: {
|
|
||||||
enableHighAccuracy: true,
|
|
||||||
},
|
|
||||||
trackUserLocation: true,
|
|
||||||
}), 'bottom-right')
|
|
||||||
.addControl(new mapBoxGL.ScaleControl({
|
|
||||||
maxWidth: 80,
|
|
||||||
unit: 'metric',
|
|
||||||
}), 'top-left')
|
|
||||||
.addControl(new mapboxgl.FullscreenControl());
|
|
||||||
|
|
||||||
$el.data('Map', Map);
|
|
||||||
$el.data('Popup', popup);
|
|
||||||
|
|
||||||
// event.target
|
|
||||||
Map.on('load', (e) => {
|
|
||||||
// Insert the layer beneath any symbol layer.
|
|
||||||
if (config['3d']) {
|
|
||||||
const layers = Map.getStyle().layers;
|
|
||||||
let labelLayerId;
|
|
||||||
for (let i = 0; i < layers.length; i++) {
|
|
||||||
if (layers[i].type === 'symbol' && layers[i].layout['text-field']) {
|
|
||||||
labelLayerId = layers[i].id;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map.addLayer({
|
|
||||||
'id': '3d-buildings',
|
|
||||||
'source': 'composite',
|
|
||||||
'source-layer': 'building',
|
|
||||||
'filter': ['==', 'extrude', 'true'],
|
|
||||||
'type': 'fill-extrusion',
|
|
||||||
'minzoom': 15,
|
|
||||||
'paint': {
|
|
||||||
'fill-extrusion-color': '#aaa',
|
|
||||||
|
|
||||||
// use an 'interpolate' expression to add a smooth transition effect to the
|
|
||||||
// buildings as the user zooms in
|
|
||||||
'fill-extrusion-height': [
|
|
||||||
"interpolate", ["linear"],
|
|
||||||
["zoom"],
|
|
||||||
15, 0,
|
|
||||||
15.05, ["get", "height"]
|
|
||||||
],
|
|
||||||
'fill-extrusion-base': [
|
|
||||||
"interpolate", ["linear"],
|
|
||||||
["zoom"],
|
|
||||||
15, 0,
|
|
||||||
15.05, ["get", "min_height"]
|
|
||||||
],
|
|
||||||
'fill-extrusion-opacity': .6
|
|
||||||
}
|
|
||||||
}, labelLayerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
const firstMarker = config['geojson'].features[0].geometry.coordinates;
|
|
||||||
//Map.setCenter(firstMarker);
|
|
||||||
const bounds = new mapBoxGL.LngLatBounds(firstMarker, firstMarker);
|
|
||||||
|
|
||||||
// add markers to map
|
|
||||||
config['geojson'].features.forEach((marker) => {
|
|
||||||
const id = marker.id;
|
|
||||||
const crds = marker.geometry.coordinates;
|
|
||||||
const content = marker.properties.content;
|
|
||||||
|
|
||||||
// create a DOM el for the marker
|
|
||||||
const $el = $(`<div id="Marker${ id }" data-id="${ id }" class="marker">${ marker.icon }</div>`);
|
|
||||||
|
|
||||||
$el.on('click', () => {
|
|
||||||
popup.setLngLat(crds)
|
|
||||||
.setHTML(content)
|
|
||||||
.addTo(Map);
|
|
||||||
|
|
||||||
if (config['flyToMarker']) {
|
|
||||||
Map.flyTo({
|
|
||||||
center: crds,
|
|
||||||
zoom: 17,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$el.trigger(Events.MAPMARKERCLICK);
|
|
||||||
});
|
|
||||||
|
|
||||||
// add marker to map
|
|
||||||
new mapBoxGL.Marker($el[0])
|
|
||||||
.setLngLat(crds)
|
|
||||||
.addTo(Map);
|
|
||||||
bounds.extend(crds);
|
|
||||||
});
|
|
||||||
|
|
||||||
Map.fitBounds(bounds, {
|
|
||||||
padding: 30,
|
|
||||||
});
|
|
||||||
|
|
||||||
popup.on('close', (e) => {
|
|
||||||
if (config['flyToBounds']) {
|
|
||||||
Map.fitBounds(bounds, {
|
|
||||||
padding: 30,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$el.trigger(Events.MAPPOPUPCLOSE);
|
|
||||||
});
|
|
||||||
|
|
||||||
$el.trigger(Events.MAPLOADED);
|
|
||||||
$(W).trigger(Events.MAPLOADED);
|
|
||||||
console.log('Map is loaded');
|
|
||||||
});
|
|
||||||
|
|
||||||
/*Map.on('render',function(event){
|
|
||||||
console.log('map moved');
|
|
||||||
console.log(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
// event: MapDataEvent
|
|
||||||
Map.on('dataloading',() => {
|
|
||||||
console.log('Loading map data');
|
|
||||||
//console.log(event);
|
|
||||||
});
|
|
||||||
|
|
||||||
// event: MapDataEvent
|
|
||||||
Map.on('data',(event) => {
|
|
||||||
console.log('Map data updated');
|
|
||||||
//console.log(event);
|
|
||||||
});*/
|
|
||||||
|
|
||||||
// check time every 60 mins and change to night style
|
|
||||||
const api = this;
|
|
||||||
setInterval(() => {
|
|
||||||
const newStyle = api.getStyle();
|
|
||||||
if (newStyle !== currentStyle) {
|
|
||||||
Map.setStyle(api.getStyle());
|
|
||||||
}
|
|
||||||
}, 36000);
|
|
||||||
|
|
||||||
|
|
||||||
$el.addClass(`${NAME}-active`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public methods
|
|
||||||
getMap() {
|
|
||||||
return Map;
|
|
||||||
}
|
|
||||||
|
|
||||||
getStyle() {
|
|
||||||
const $el = $(this._el);
|
|
||||||
return $el.data('map-style');
|
|
||||||
return 'mapbox://styles/mapbox/streets-v9';
|
|
||||||
const hour = new Date().getHours();
|
|
||||||
if (hour < 6 || hour > 18) {
|
|
||||||
// night
|
|
||||||
//return 'mapbox://styles/mapbox/streets-v7';
|
|
||||||
return 'mapbox://styles/tony-air/cjeacwih92iu42rpd8tcmuyb2';
|
|
||||||
}
|
|
||||||
// day
|
|
||||||
return 'mapbox://styles/mapbox/streets-v9';
|
|
||||||
}
|
|
||||||
|
|
||||||
dispose() {
|
|
||||||
const $el = $(this._el);
|
|
||||||
|
|
||||||
$el.removeClass(`${NAME}-active`);
|
|
||||||
$.removeData(this._el, DATA_KEY);
|
|
||||||
this._el = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static _jQueryInterface() {
|
|
||||||
if (typeof W.localStorage !== 'undefined') {
|
|
||||||
return this.each(function() {
|
|
||||||
// attach functionality to el
|
|
||||||
const $el = $(this);
|
|
||||||
let data = $el.data(DATA_KEY);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
data = new MapAPI(this);
|
|
||||||
$el.data(DATA_KEY, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jQuery interface
|
|
||||||
$.fn[NAME] = MapAPI._jQueryInterface;
|
|
||||||
$.fn[NAME].Constructor = MapAPI;
|
|
||||||
$.fn[NAME].noConflict = function() {
|
|
||||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
|
||||||
return MapAPI._jQueryInterface;
|
|
||||||
};
|
|
||||||
|
|
||||||
// auto-apply
|
|
||||||
$(W).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
|
||||||
$('.mapAPI-map-container').jsMapAPI();
|
|
||||||
});
|
|
||||||
|
|
||||||
return MapAPI;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default MapAPI;
|
|
@ -1,62 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
const SlidingMenu = (($) => {
|
|
||||||
// Constants
|
|
||||||
const NAME = 'jsSlidingMenu';
|
|
||||||
const DATA_KEY = NAME;
|
|
||||||
|
|
||||||
class SlidingMenu {
|
|
||||||
// Constructor
|
|
||||||
constructor(el) {
|
|
||||||
const $el = $(this._el);
|
|
||||||
this.$el = $el;
|
|
||||||
$el.addClass(`${NAME}-active`);
|
|
||||||
|
|
||||||
// esc button
|
|
||||||
$(window).on('keyup', ((e) => {
|
|
||||||
if (e.which === 27) {
|
|
||||||
$el.find('.is-open[data-toggle="offcanvas"]').click();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public methods
|
|
||||||
dispose() {
|
|
||||||
console.log(`Disposing: ${NAME} els`);
|
|
||||||
|
|
||||||
this.$el.removeClass(`${NAME}-active`);
|
|
||||||
$.removeData(this.$el, DATA_KEY);
|
|
||||||
this.$el = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static _jQueryInterface() {
|
|
||||||
return this.each(function() {
|
|
||||||
// attach functionality to el
|
|
||||||
const $el = $(this);
|
|
||||||
let data = $el.data(DATA_KEY);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
data = new SlidingMenu(this);
|
|
||||||
$el.data(DATA_KEY, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jQuery interface
|
|
||||||
$.fn[NAME] = SlidingMenu._jQueryInterface;
|
|
||||||
$.fn[NAME].Constructor = SlidingMenu;
|
|
||||||
$.fn[NAME].noConflict = function() {
|
|
||||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
|
||||||
return SlidingMenu._jQueryInterface;
|
|
||||||
};
|
|
||||||
|
|
||||||
// auto-apply
|
|
||||||
$(`.ui.${NAME}`).ready(() => {
|
|
||||||
$(`.ui.${NAME}`).jsSlidingMenu();
|
|
||||||
});
|
|
||||||
|
|
||||||
return SlidingMenu;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default SlidingMenu;
|
|
@ -1,72 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
import Events from '../_events';
|
|
||||||
import Spinner from './_ui.spinner';
|
|
||||||
|
|
||||||
const NoCaptcha = (($) => {
|
|
||||||
// Constants
|
|
||||||
const W = window;
|
|
||||||
const D = document;
|
|
||||||
const $Body = $('body');
|
|
||||||
|
|
||||||
const NAME = 'NoCaptcha';
|
|
||||||
|
|
||||||
class NoCaptcha {
|
|
||||||
static init() {
|
|
||||||
const ui = this;
|
|
||||||
ui.dispose();
|
|
||||||
|
|
||||||
console.log(`Initializing: ${NAME}`);
|
|
||||||
this.renderCaptcha();
|
|
||||||
}
|
|
||||||
|
|
||||||
static dispose() {
|
|
||||||
console.log(`Destroying: ${NAME}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
static renderCaptcha() {
|
|
||||||
console.log(`Rendering Captcha: ${NAME}`);
|
|
||||||
|
|
||||||
if (typeof grecaptcha === 'undefined') {
|
|
||||||
console.log('Captcha API isn\'t available yet');
|
|
||||||
}
|
|
||||||
|
|
||||||
const $_noCaptchaFields = $('.g-recaptcha');
|
|
||||||
|
|
||||||
const submitListener = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
grecaptcha.execute();
|
|
||||||
};
|
|
||||||
|
|
||||||
$_noCaptchaFields.each((i, field) => {
|
|
||||||
const $field = $(field);
|
|
||||||
|
|
||||||
if ($field.data('widgetid')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const $form = $field.data('form') ? $(`#${ $field.data('form')}`) : $field.parents('form');
|
|
||||||
|
|
||||||
//For the invisible captcha we need to setup some callback listeners
|
|
||||||
if ($field.data('size') === 'invisible' && !$field.data('callback')) {
|
|
||||||
$form.on('submit', submitListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
const widget_id = grecaptcha.render(field, $field.data());
|
|
||||||
$field.data('widgetid', widget_id);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$(W).on(`${Events.AJAX}`, () => {
|
|
||||||
NoCaptcha.init();
|
|
||||||
});
|
|
||||||
|
|
||||||
W.NoCaptcha = NoCaptcha;
|
|
||||||
W.noCaptchaFieldRender = NoCaptcha.renderCaptcha;
|
|
||||||
|
|
||||||
return NoCaptcha;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default NoCaptcha;
|
|
@ -1,108 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
import Events from '../_events';
|
|
||||||
|
|
||||||
const OpeningHoursUI = (($) => {
|
|
||||||
// Constants
|
|
||||||
const NAME = 'OpeningHoursUI';
|
|
||||||
|
|
||||||
class OpeningHoursUI {
|
|
||||||
// Static methods
|
|
||||||
|
|
||||||
static each(callback) {
|
|
||||||
$('.js-opening-hours').each((i, e) => {
|
|
||||||
callback(i, $(e));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static init() {
|
|
||||||
this.dispose();
|
|
||||||
const hours = $.parseJSON($('.oppening-hours-json').html());
|
|
||||||
const date = new Date();
|
|
||||||
const dateYMD = this.Date_toYMD(date);
|
|
||||||
const weekday = [
|
|
||||||
'Sunday',
|
|
||||||
'Monday',
|
|
||||||
'Tuesday',
|
|
||||||
'Wednesday',
|
|
||||||
'Thursday',
|
|
||||||
'Friday',
|
|
||||||
'Saturday',
|
|
||||||
];
|
|
||||||
const today = weekday[date.getDay()];
|
|
||||||
let html = '<b class="opening-hours-status opening-hours-status-closed">Closed today</b>';
|
|
||||||
|
|
||||||
if (
|
|
||||||
typeof hours['days'] !== 'undefined' &&
|
|
||||||
typeof hours['days'][today] !== 'undefined' &&
|
|
||||||
hours['days'][today].length
|
|
||||||
) {
|
|
||||||
html = 'Open today ';
|
|
||||||
$.each(hours['days'][today], (i, v) => {
|
|
||||||
if (v['DisplayStart'] || v['DisplayEnd']) {
|
|
||||||
if (
|
|
||||||
(
|
|
||||||
v['DisplayStart'] && v['DisplayStart'] <= dateYMD &&
|
|
||||||
v['DisplayEnd'] && v['DisplayEnd'] >= dateYMD
|
|
||||||
) ||
|
|
||||||
(v['DisplayStart'] && v['DisplayStart'] <= dateYMD && !v['DisplayEnd']) ||
|
|
||||||
(v['DisplayEnd'] && v['DisplayEnd'] >= dateYMD && !v['DisplayStart'])
|
|
||||||
) {
|
|
||||||
html = `Open today from ${ v['From'] } to ${ v['Till']}`;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (i > 0) {
|
|
||||||
html += ', <br/>';
|
|
||||||
}
|
|
||||||
html += `from ${ v['From'] } to ${ v['Till']}`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
html += ' <b class="opening-hours-status"></b>';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
typeof hours['holidays'] !== 'undefined' &&
|
|
||||||
typeof hours['holidays'][dateYMD] !== 'undefined'
|
|
||||||
) {
|
|
||||||
html = `<b class="opening-hours-status opening-hours-status-closed">Closed today${
|
|
||||||
hours['holidays'][dateYMD] ? ` for ${ hours['holidays'][dateYMD]}` : ''
|
|
||||||
}</b>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.each((i, e) => {
|
|
||||||
const $e = $(e);
|
|
||||||
$e.html(html);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static Date_toYMD(date) {
|
|
||||||
var year, month, day;
|
|
||||||
year = String(date.getFullYear());
|
|
||||||
month = String(date.getMonth() + 1);
|
|
||||||
if (month.length == 1) {
|
|
||||||
month = `0${ month}`;
|
|
||||||
}
|
|
||||||
day = String(date.getDate());
|
|
||||||
if (day.length == 1) {
|
|
||||||
day = `0${ day}`;
|
|
||||||
}
|
|
||||||
return `${year }-${ month }-${ day}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static dispose() {
|
|
||||||
this.each((i, e) => {
|
|
||||||
$(e).html('');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
|
||||||
OpeningHoursUI.init();
|
|
||||||
});
|
|
||||||
|
|
||||||
return OpeningHoursUI;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default OpeningHoursUI;
|
|
@ -1,22 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
const ShrinkUI = (($) => {
|
|
||||||
// Constants
|
|
||||||
const G = window;
|
|
||||||
const D = document;
|
|
||||||
|
|
||||||
// shrink bar
|
|
||||||
$(G).scroll(() => {
|
|
||||||
if ($(D).scrollTop() > 100) {
|
|
||||||
$('body').addClass('shrink');
|
|
||||||
} else {
|
|
||||||
$('body').removeClass('shrink');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return ShrinkUI;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default ShrinkUI;
|
|
@ -1,17 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
const SpinnerUI = (($) => {
|
|
||||||
class SpinnerUI {
|
|
||||||
static show(callback) {
|
|
||||||
$('#PageLoading').show(0, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
static hide(callback) {
|
|
||||||
$('#PageLoading').hide('slow', callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SpinnerUI;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default SpinnerUI;
|
|
@ -1,108 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
import MainUI from "../_main";
|
|
||||||
import Events from '../_events';
|
|
||||||
import SpinnerUI from './_ui.spinner';
|
|
||||||
|
|
||||||
const VideoPreviewUI = (($) => {
|
|
||||||
|
|
||||||
const NAME = 'jsVideoPreviewUI';
|
|
||||||
const DATA_KEY = NAME;
|
|
||||||
|
|
||||||
const G = window;
|
|
||||||
const D = document;
|
|
||||||
|
|
||||||
class VideoPreviewUI {
|
|
||||||
|
|
||||||
constructor(el) {
|
|
||||||
console.log(`Initializing: ${NAME}`);
|
|
||||||
|
|
||||||
const ui = this;
|
|
||||||
ui.$_el = $(el);
|
|
||||||
ui.innerHTML = ui.$_el[0].innerHTML;
|
|
||||||
|
|
||||||
ui.$_el.data(DATA_KEY, this);
|
|
||||||
const href = ui.$_el.attr('href') || ui.$_el.data('href');
|
|
||||||
const YouTubeGetID = (url) => {
|
|
||||||
url = url.split(/(vi\/|v%3D|v=|\/v\/|youtu\.be\/|\/embed\/)/);
|
|
||||||
return undefined !== url[2] ? url[2].split(/[^0-9a-z_\-]/i)[0] : url[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
let video;
|
|
||||||
|
|
||||||
if (video = href.match(/(youtube|youtube-nocookie|youtu|vimeo)\.(com|be)\/(watch\?v=([\w-]+)|([\w-]+))/)) {
|
|
||||||
let video_id;
|
|
||||||
|
|
||||||
if (video[1] === 'youtube' || video[1] === 'youtube-nocookie' || video[1] === 'youtu') {
|
|
||||||
video_id = YouTubeGetID(href);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (video[1] == 'vimeo') {
|
|
||||||
video_id = video[3];
|
|
||||||
ui.$_el.addClass('loading');
|
|
||||||
$.ajax({
|
|
||||||
type: 'GET',
|
|
||||||
url: `https://vimeo.com/api/v2/video/${ video_id }.json`,
|
|
||||||
jsonp: 'callback',
|
|
||||||
dataType: 'jsonp',
|
|
||||||
success: function(data) {
|
|
||||||
const thumbnail_src = data[0].thumbnail_large;
|
|
||||||
ui.show(thumbnail_src);
|
|
||||||
ui.$_el.removeClass('loading');
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (video_id) {
|
|
||||||
ui.show(`//i3.ytimg.com/vi/${video_id}/0.jpg`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
show(src) {
|
|
||||||
const ui = this;
|
|
||||||
ui.$_el[0].innerHTML = '';
|
|
||||||
ui.$_el.append(`<img src="${src}" alt="Video" />`);
|
|
||||||
}
|
|
||||||
|
|
||||||
static dispose() {
|
|
||||||
console.log(`Destroying: ${NAME}`);
|
|
||||||
ui.$_el[0].innerHTML = ui.innerHTML;
|
|
||||||
}
|
|
||||||
|
|
||||||
static _jQueryInterface() {
|
|
||||||
return this.each((i, el) => {
|
|
||||||
// attach functionality to element
|
|
||||||
const $el = $(el);
|
|
||||||
let data = $el.data(DATA_KEY);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
data = new VideoPreviewUI(el);
|
|
||||||
$el.data(DATA_KEY, data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jQuery interface
|
|
||||||
$.fn[NAME] = VideoPreviewUI._jQueryInterface;
|
|
||||||
$.fn[NAME].Constructor = VideoPreviewUI;
|
|
||||||
$.fn[NAME].noConflict = () => {
|
|
||||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
|
||||||
return VideoPreviewUI._jQueryInterface;
|
|
||||||
};
|
|
||||||
|
|
||||||
// auto-apply
|
|
||||||
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
|
||||||
$('[data-video-preview="true"]').jsVideoPreviewUI();
|
|
||||||
});
|
|
||||||
|
|
||||||
return VideoPreviewUI;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default VideoPreviewUI;
|
|
@ -1,30 +0,0 @@
|
|||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
const G = window;
|
|
||||||
const D = document;
|
|
||||||
|
|
||||||
// remove browser default alerts
|
|
||||||
/*alert = function () {
|
|
||||||
console.log(arguments);
|
|
||||||
console.log(new Error().stack);
|
|
||||||
};*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*G.addEventListener(G.visibilityChangeEvent, () => {
|
|
||||||
if (currentPage && typeof currentPage !== 'undefined') {
|
|
||||||
if (
|
|
||||||
landingPage !== G.location.href &&
|
|
||||||
currentPage !== '/' &&
|
|
||||||
currentPage.indexOf('/dev') === -1 &&
|
|
||||||
!$('main>div').hasClass('type-ErrorPage')
|
|
||||||
) {
|
|
||||||
G.localStorage.setItem('current-page', G.location.href);
|
|
||||||
} else if (landingPage === G.location.href || currentPage.indexOf('/dev') !== -1) {
|
|
||||||
G.localStorage.removeItem('current-page');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});*/
|
|
@ -1,270 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
import mapbox from "mapbox-gl";
|
|
||||||
|
|
||||||
window.offlineMaps = {};
|
|
||||||
|
|
||||||
window.offlineMaps.eventManager = {
|
|
||||||
_events: {},
|
|
||||||
|
|
||||||
on: function (event, action) {
|
|
||||||
console.log(`event.on: ${ event}`);
|
|
||||||
if (!(event in this._events)) {
|
|
||||||
this._events[event] = [];
|
|
||||||
}
|
|
||||||
this._events[event].push(action);
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
off: function (event) {
|
|
||||||
console.log(`event.off: ${ event}`);
|
|
||||||
delete this._events[event];
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
fire: function (event) {
|
|
||||||
console.log(`event.fire: ${ event}`);
|
|
||||||
var events = this._events;
|
|
||||||
if (event in events) {
|
|
||||||
var actions = events[event];
|
|
||||||
var args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
for (var i = 0, l = actions.length; i < l; i++) {
|
|
||||||
var action = actions[i];
|
|
||||||
if (action instanceof Function) {
|
|
||||||
action.apply(null, args);
|
|
||||||
} else {
|
|
||||||
this.fire.apply(this, [action].concat(args));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
(function (window, emr, undefined) {
|
|
||||||
var getIndexedDBStorage = function () {
|
|
||||||
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
|
|
||||||
|
|
||||||
var IndexedDBImpl = function () {
|
|
||||||
var self = this;
|
|
||||||
var db = null;
|
|
||||||
var request = indexedDB.open('TileStorage');
|
|
||||||
|
|
||||||
request.onsuccess = function() {
|
|
||||||
db = this.result;
|
|
||||||
emr.fire('storageLoaded', self);
|
|
||||||
};
|
|
||||||
|
|
||||||
request.onerror = function (error) {
|
|
||||||
console.log(error);
|
|
||||||
};
|
|
||||||
|
|
||||||
request.onupgradeneeded = function () {
|
|
||||||
var store = this.result.createObjectStore('tile', { keyPath: 'key' });
|
|
||||||
store.createIndex('key', 'key', { unique: true });
|
|
||||||
};
|
|
||||||
|
|
||||||
this.add = function (key, value) {
|
|
||||||
var transaction = db.transaction(['tile'], 'readwrite');
|
|
||||||
var objectStore = transaction.objectStore('tile');
|
|
||||||
objectStore.put({ key, value });
|
|
||||||
};
|
|
||||||
|
|
||||||
this.delete = function (key) {
|
|
||||||
var transaction = db.transaction(['tile'], 'readwrite');
|
|
||||||
var objectStore = transaction.objectStore('tile');
|
|
||||||
objectStore.delete(key);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.get = function (key, successCallback, errorCallback) {
|
|
||||||
var transaction = db.transaction(['tile'], 'readonly');
|
|
||||||
var objectStore = transaction.objectStore('tile');
|
|
||||||
var result = objectStore.get(key);
|
|
||||||
result.onsuccess = function () {
|
|
||||||
successCallback(this.result ? this.result.value : undefined);
|
|
||||||
};
|
|
||||||
result.onerror = errorCallback;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return indexedDB ? new IndexedDBImpl() : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
var getWebSqlStorage = function () {
|
|
||||||
var openDatabase = window.openDatabase;
|
|
||||||
|
|
||||||
var WebSqlImpl = function () {
|
|
||||||
var self = this;
|
|
||||||
var db = openDatabase('TileStorage', '1.0', 'Tile Storage', 5 * 1024 * 1024);
|
|
||||||
db.transaction((tx) => {
|
|
||||||
tx.executeSql('CREATE TABLE IF NOT EXISTS tile (key TEXT PRIMARY KEY, value TEXT)', [], () => {
|
|
||||||
emr.fire('storageLoaded', self);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
this.add = function (key, value) {
|
|
||||||
db.transaction((tx) => {
|
|
||||||
tx.executeSql('INSERT INTO tile (key, value) VALUES (?, ?)', [key, value]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.delete = function (key) {
|
|
||||||
db.transaction((tx) => {
|
|
||||||
tx.executeSql('DELETE FROM tile WHERE key = ?', [key]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.get = function (key, successCallback, errorCallback) {
|
|
||||||
db.transaction((tx) => {
|
|
||||||
tx.executeSql('SELECT value FROM tile WHERE key = ?', [key], (tx, result) => {
|
|
||||||
successCallback(result.rows.length ? result.rows.item(0).value : undefined);
|
|
||||||
}, errorCallback);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return openDatabase ? new WebSqlImpl() : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
emr.on('storageLoad', () => {
|
|
||||||
var storage = getIndexedDBStorage() || getWebSqlStorage() || null;
|
|
||||||
if (!storage) {
|
|
||||||
emr.fire('storageLoaded', null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})(window, window.offlineMaps.eventManager);
|
|
||||||
|
|
||||||
(function (window, emr, mapbox, MM, undefined) {
|
|
||||||
var StorageRequestManager = function (storage) {
|
|
||||||
MM.RequestManager.apply(this, []);
|
|
||||||
this._storage = storage;
|
|
||||||
};
|
|
||||||
|
|
||||||
StorageRequestManager.prototype._imageToDataUri = function (image) {
|
|
||||||
var canvas = window.document.createElement('canvas');
|
|
||||||
canvas.width = image.width;
|
|
||||||
canvas.height = image.height;
|
|
||||||
|
|
||||||
var context = canvas.getContext('2d');
|
|
||||||
context.drawImage(image, 0, 0);
|
|
||||||
|
|
||||||
return canvas.toDataURL('image/png');
|
|
||||||
};
|
|
||||||
|
|
||||||
StorageRequestManager.prototype._createTileImage = function (id, coord, value, cache) {
|
|
||||||
var img = window.document.createElement('img');
|
|
||||||
img.id = id;
|
|
||||||
img.style.position = 'absolute';
|
|
||||||
img.coord = coord;
|
|
||||||
this.loadingBay.appendChild(img);
|
|
||||||
if (cache) {
|
|
||||||
img.onload = this.getLoadCompleteWithCache();
|
|
||||||
img.crossOrigin = 'Anonymous';
|
|
||||||
} else {
|
|
||||||
img.onload = this.getLoadComplete();
|
|
||||||
}
|
|
||||||
img.onerror = this.getLoadComplete();
|
|
||||||
img.src = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
StorageRequestManager.prototype._loadTile = function (id, coord, url) {
|
|
||||||
var self = this;
|
|
||||||
if (this._storage) {
|
|
||||||
this._storage.get(id, (value) => {
|
|
||||||
if (value) {
|
|
||||||
self._createTileImage(id, coord, value, false);
|
|
||||||
} else {
|
|
||||||
self._createTileImage(id, coord, url, true);
|
|
||||||
}
|
|
||||||
}, () => {
|
|
||||||
self._createTileImage(id, coord, url, true);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
self._createTileImage(id, coord, url, false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
StorageRequestManager.prototype.processQueue = function (sortFunc) {
|
|
||||||
if (sortFunc && this.requestQueue.length > 8) {
|
|
||||||
this.requestQueue.sort(sortFunc);
|
|
||||||
}
|
|
||||||
while (this.openRequestCount < this.maxOpenRequests && this.requestQueue.length > 0) {
|
|
||||||
var request = this.requestQueue.pop();
|
|
||||||
if (request) {
|
|
||||||
this.openRequestCount++;
|
|
||||||
this._loadTile(request.id, request.coord, request.url);
|
|
||||||
request = request.id = request.coord = request.url = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
StorageRequestManager.prototype.getLoadCompleteWithCache = function () {
|
|
||||||
if (!this._loadComplete) {
|
|
||||||
var theManager = this;
|
|
||||||
this._loadComplete = function(e) {
|
|
||||||
//e = e || window.event;
|
|
||||||
|
|
||||||
var img = e.srcElement || e.target;
|
|
||||||
img.onload = img.onerror = null;
|
|
||||||
|
|
||||||
if (theManager._storage) {
|
|
||||||
theManager._storage.add(this.id, theManager._imageToDataUri(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
theManager.loadingBay.removeChild(img);
|
|
||||||
theManager.openRequestCount--;
|
|
||||||
delete theManager.requestsById[img.id];
|
|
||||||
|
|
||||||
if (e.type === 'load' && (img.complete ||
|
|
||||||
(img.readyState && img.readyState === 'complete'))) {
|
|
||||||
theManager.dispatchCallback('requestcomplete', img);
|
|
||||||
} else {
|
|
||||||
theManager.dispatchCallback('requesterror', {
|
|
||||||
element: img,
|
|
||||||
url: (`${ img.src}`),
|
|
||||||
});
|
|
||||||
img.src = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(theManager.getProcessQueue(), 0);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return this._loadComplete;
|
|
||||||
};
|
|
||||||
|
|
||||||
MM.extend(StorageRequestManager, MM.RequestManager);
|
|
||||||
|
|
||||||
var StorageLayer = function(provider, parent, name, storage) {
|
|
||||||
this.parent = parent || document.createElement('div');
|
|
||||||
this.parent.style.cssText = 'position: absolute; top: 0px; left: 0px;' +
|
|
||||||
'width: 100%; height: 100%; margin: 0; padding: 0; z-index: 0';
|
|
||||||
this.name = name;
|
|
||||||
this.levels = {};
|
|
||||||
this.requestManager = new StorageRequestManager(storage);
|
|
||||||
this.requestManager.addCallback('requestcomplete', this.getTileComplete());
|
|
||||||
this.requestManager.addCallback('requesterror', this.getTileError());
|
|
||||||
if (provider) {
|
|
||||||
this.setProvider(provider);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MM.extend(StorageLayer, MM.Layer);
|
|
||||||
|
|
||||||
var StorageTemplatedLayer = function(template, subdomains, name, storage) {
|
|
||||||
return new StorageLayer(new MM.Template(template, subdomains), null, name, storage);
|
|
||||||
};
|
|
||||||
|
|
||||||
emr.on('mapLoad', (storage) => {
|
|
||||||
var map = mapbox.map('map');
|
|
||||||
map.addLayer(new StorageTemplatedLayer('http://{S}.tile.osm.org/{Z}/{X}/{Y}.png',
|
|
||||||
['a', 'b', 'c'], undefined, storage));
|
|
||||||
map.ui.zoomer.add();
|
|
||||||
map.ui.zoombox.add();
|
|
||||||
map.centerzoom({ lat: 53.902254, lon: 27.561850 }, 13);
|
|
||||||
});
|
|
||||||
})(window, window.offlineMaps.eventManager, mapbox, MM);
|
|
||||||
|
|
||||||
(function (emr) {
|
|
||||||
emr.on('storageLoaded', 'mapLoad');
|
|
||||||
emr.fire('storageLoad');
|
|
||||||
})(window.offlineMaps.eventManager);
|
|
@ -1,13 +0,0 @@
|
|||||||
import Events from '../../_events';
|
|
||||||
import Routie from "routie";
|
|
||||||
|
|
||||||
$(window).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
|
||||||
Routie({
|
|
||||||
'navigation': function() {
|
|
||||||
$('#NavbarCollapse').addClass('in');
|
|
||||||
},
|
|
||||||
'carousel:id:num': function(id, num) {
|
|
||||||
$(`#Carousel${ id}`).carousel(num);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,23 +0,0 @@
|
|||||||
/**
|
|
||||||
* Add your global events here
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
AJAX: 'ajax-load',
|
|
||||||
LOADED: 'load',
|
|
||||||
MAPLOADED: 'map-loaded',
|
|
||||||
MAPMARKERCLICK: 'map-marker-click',
|
|
||||||
MAPPOPUPCLOSE: 'map-popup-close',
|
|
||||||
SET_TARGET_UPDATE: 'set-target-update',
|
|
||||||
RESTORE_FIELD: 'restore-field',
|
|
||||||
FORM_INIT_BASICS: 'form-basics',
|
|
||||||
FORM_INIT_STEPPED: 'form-init-stepped',
|
|
||||||
FORM_INIT_VALIDATE: 'form-init-validate',
|
|
||||||
FORM_INIT_VALIDATE_FIELD: 'form-init-validate-field',
|
|
||||||
FORM_INIT_STORAGE: 'form-init-storage',
|
|
||||||
FORM_VALIDATION_FAILED: 'form-validation-failed',
|
|
||||||
FORM_STEPPED_NEW_STEP: 'form-new-step',
|
|
||||||
FORM_STEPPED_FIRST_STEP: 'form-first-step',
|
|
||||||
FORM_STEPPED_LAST_STEP: 'form-last-step',
|
|
||||||
FORM_FIELDS: 'input,textarea,select',
|
|
||||||
};
|
|
@ -1,10 +1,13 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
|
||||||
import Events from './_events';
|
import Events from 'ss-bootstrap-ui-webpack-boilerplate/src/js/_events';
|
||||||
import Spinner from './_components/_ui.spinner';
|
import Spinner from 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.spinner';
|
||||||
import FormDatetime from './_components/_ui.form.datetime';
|
import FormDatetime from 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.datetime';
|
||||||
import FormStepped from './_components/_ui.form.stepped';
|
import FormStepped from 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.stepped';
|
||||||
|
|
||||||
|
//import Multislider from 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.multislider';
|
||||||
|
|
||||||
const LayoutUI = (($) => {
|
const LayoutUI = (($) => {
|
||||||
// Constants
|
// Constants
|
||||||
|
@ -1,384 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
import $ from 'jquery';
|
|
||||||
|
|
||||||
import 'hammerjs/hammer';
|
|
||||||
import 'jquery-hammerjs/jquery.hammer';
|
|
||||||
|
|
||||||
//import Confirmation from 'bootstrap-confirmation2/dist/bootstrap-confirmation';
|
|
||||||
//import Table from 'bootstrap-table/dist/bootstrap-table';
|
|
||||||
|
|
||||||
// Routie
|
|
||||||
import 'pouchdb/dist/pouchdb';
|
|
||||||
import './_components/routes/index';
|
|
||||||
|
|
||||||
import Events from './_events';
|
|
||||||
import Spinner from './_components/_ui.spinner';
|
|
||||||
|
|
||||||
// AJAX functionality
|
|
||||||
import AjaxUI from './_components/_ui.ajax';
|
|
||||||
import './_components/_ui.carousel';
|
|
||||||
import './_components/_ui.menu';
|
|
||||||
|
|
||||||
// Bootstrap hover menu
|
|
||||||
import './_components/_ui.hover';
|
|
||||||
|
|
||||||
|
|
||||||
import FormBasics from './_components/_ui.form.basics';
|
|
||||||
|
|
||||||
// Toggle bootstrap form fields
|
|
||||||
//import FormToggleUI from './_components/_ui.form.fields.toggle';
|
|
||||||
|
|
||||||
// Bootstrap Date & Time fields
|
|
||||||
//import FormDatetime from './_components/_ui.form.datetime';
|
|
||||||
|
|
||||||
// Stepped forms functionality
|
|
||||||
//import FormStepped from './_components/_ui.form.stepped';
|
|
||||||
|
|
||||||
// Forms validation functionality
|
|
||||||
//import FormValidate from './_components/_ui.form.validate';
|
|
||||||
|
|
||||||
// Store forms data into localStorage
|
|
||||||
//import FormStorage from './_components/_ui.form.storage';
|
|
||||||
|
|
||||||
// client-side images cropping
|
|
||||||
//import FormCroppie from './_components/_ui.form.croppie';
|
|
||||||
|
|
||||||
// Google NoCaptcha fields
|
|
||||||
//import NoCaptcha from './_components/_ui.nocaptcha';
|
|
||||||
|
|
||||||
import SmoothScroll from 'smooth-scroll';
|
|
||||||
const smoothScroll = SmoothScroll();
|
|
||||||
|
|
||||||
const MainUI = (($) => {
|
|
||||||
// Constants
|
|
||||||
const W = window;
|
|
||||||
const D = document;
|
|
||||||
const $Body = $('body');
|
|
||||||
|
|
||||||
const NAME = 'MainUI';
|
|
||||||
|
|
||||||
// get browser locale
|
|
||||||
//const Locale = $('html').attr('lang').substring(0, 2);
|
|
||||||
|
|
||||||
const $AlertNotify = $('#AlertNotify');
|
|
||||||
const $SiteWideMessage = $('#SiteWideMessage');
|
|
||||||
|
|
||||||
// get browser window visibility preferences
|
|
||||||
// Opera 12.10, Firefox >=18, Chrome >=31, IE11
|
|
||||||
const HiddenName = 'hidden';
|
|
||||||
const VisibilityChangeEvent = 'visibilitychange';
|
|
||||||
|
|
||||||
// update visibility state
|
|
||||||
D.addEventListener(VisibilityChangeEvent, () => {
|
|
||||||
if (D.visibilityState === HiddenName) {
|
|
||||||
console.log('Tab: hidden');
|
|
||||||
$Body.addClass('is-hidden');
|
|
||||||
$Body.trigger('tabHidden');
|
|
||||||
} else {
|
|
||||||
console.log('Tab: focused');
|
|
||||||
$Body.removeClass('is-hidden');
|
|
||||||
$Body.trigger('tabFocused');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// update online/offline state
|
|
||||||
const updateOnlineStatus = function() {
|
|
||||||
if (!navigator.onLine) {
|
|
||||||
console.log('Tab: offline');
|
|
||||||
$Body.addClass('is-offline');
|
|
||||||
$Body.trigger('offline');
|
|
||||||
} else {
|
|
||||||
console.log('Tab: online');
|
|
||||||
$Body.removeClass('is-offline');
|
|
||||||
$Body.trigger('online');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (typeof navigator.onLine !== 'undefined') {
|
|
||||||
W.addEventListener('offline', () => {
|
|
||||||
updateOnlineStatus();
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
W.addEventListener('online', () => {
|
|
||||||
updateOnlineStatus();
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
W.addEventListener('load', () => {
|
|
||||||
updateOnlineStatus();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// scrollTo
|
|
||||||
const ScrollTo = function(trigger, selector) {
|
|
||||||
smoothScroll.animateScroll(
|
|
||||||
D.querySelector(selector),
|
|
||||||
trigger, {
|
|
||||||
speed: 500,
|
|
||||||
offset: -20,
|
|
||||||
//easing: 'easeInOutCubic',
|
|
||||||
// Callback API
|
|
||||||
//before: function (anchor, toggle) {}, // Callback to run before scroll
|
|
||||||
//`after: function (anchor, toggle) {} // Callback to run after scroll
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
// session ping
|
|
||||||
setInterval(() => {
|
|
||||||
if ($Body.hasClass('is-offline')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
sync: false,
|
|
||||||
async: true,
|
|
||||||
cache: false,
|
|
||||||
url: '/Security/ping',
|
|
||||||
global: false,
|
|
||||||
type: 'POST',
|
|
||||||
complete(data, datastatus) {
|
|
||||||
if (datastatus !== 'success') {
|
|
||||||
W.location.reload(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}, 300000); // 5 min in ms
|
|
||||||
|
|
||||||
W.URLDetails = {
|
|
||||||
'base': $('base').attr('href'),
|
|
||||||
'relative': '/',
|
|
||||||
'hash': '',
|
|
||||||
};
|
|
||||||
|
|
||||||
class MainUI {
|
|
||||||
// Static methods
|
|
||||||
|
|
||||||
static init() {
|
|
||||||
this.dispose();
|
|
||||||
|
|
||||||
console.log(`Initializing: ${NAME}`);
|
|
||||||
|
|
||||||
// update location details
|
|
||||||
this.updateLocation();
|
|
||||||
|
|
||||||
// mark available offline areas
|
|
||||||
if ('caches' in W) {
|
|
||||||
$('a.offline').addClass('offline-available');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof AjaxUI !== 'undefined') {
|
|
||||||
this.loadImages();
|
|
||||||
}
|
|
||||||
|
|
||||||
// mark external links
|
|
||||||
$('a.external,a[rel="external"]').attr('target', '_blank');
|
|
||||||
|
|
||||||
// show encoded emails
|
|
||||||
/*$(D).find('.obm').each(function () {
|
|
||||||
if ($(this).attr('data-val') !== undefined) {
|
|
||||||
const email = $(this).attr('data-val').split('')
|
|
||||||
.reverse()
|
|
||||||
.join('')
|
|
||||||
.slice(0, -8)
|
|
||||||
.replace(/[a-zA-Z]/g, (c) => String.fromCharCode((c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26))
|
|
||||||
.replace('#AT#', '@');
|
|
||||||
const attr = $(this).attr('data-val-append');
|
|
||||||
if (attr !== undefined && attr !== false) {
|
|
||||||
$(this).append(email);
|
|
||||||
}
|
|
||||||
if ($(this).find('.sr-only').length > 0) {
|
|
||||||
$(this).find('.sr-only').append(email);
|
|
||||||
}
|
|
||||||
if ($(this).attr('href') !== undefined) {
|
|
||||||
$(this).attr('href', `mailto:${email}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});*/
|
|
||||||
//
|
|
||||||
|
|
||||||
// scroll links
|
|
||||||
$(D).on('click', '.js-scrollTo', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
const el = e.currentTarget;
|
|
||||||
const $el = $(e.currentTarget);
|
|
||||||
const target = $el.data('target') || $el.attr('href');
|
|
||||||
|
|
||||||
if ($(target).length) {
|
|
||||||
ScrollTo(el, target);
|
|
||||||
} else {
|
|
||||||
console.log(`[ScrollTo] Undefined target: ${ target}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// load external fonts
|
|
||||||
if ($('[data-extfont]').length) {
|
|
||||||
$.getScript('//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js', () => {
|
|
||||||
const fonts = [];
|
|
||||||
|
|
||||||
$('[data-extfont]').each((i, el) => {
|
|
||||||
fonts[i] = $(el).attr('data-extfont');
|
|
||||||
});
|
|
||||||
|
|
||||||
W.WebFont.load({
|
|
||||||
google: {
|
|
||||||
families: fonts,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// data-set links
|
|
||||||
$('[data-set-target]').on('click', (e) => {
|
|
||||||
const $el = $(e.currentTarget);
|
|
||||||
const $target = $($el.data('set-target'));
|
|
||||||
|
|
||||||
if (!$target.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$target.each((i, targetEl) => {
|
|
||||||
const $targetEl = $(targetEl);
|
|
||||||
const tag = $targetEl.prop('tagName').toLowerCase();
|
|
||||||
|
|
||||||
if (tag === 'input' || tag === 'select') {
|
|
||||||
$targetEl.val($el.data('set-val'));
|
|
||||||
} else if (!$targetEl.hasClass('field')) {
|
|
||||||
$targetEl.text($el.data('set-val'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$el.trigger(Events.SET_TARGET_UPDATE);
|
|
||||||
$target.closest('form').trigger(Events.SET_TARGET_UPDATE);
|
|
||||||
});
|
|
||||||
|
|
||||||
// hide spinner
|
|
||||||
Spinner.hide(() => {
|
|
||||||
$Body.addClass('loaded');
|
|
||||||
});
|
|
||||||
|
|
||||||
// fire page printing
|
|
||||||
if (W.URLDetails['hash'].indexOf('printpage') > -1) {
|
|
||||||
W.print();
|
|
||||||
}
|
|
||||||
|
|
||||||
// load youtube API
|
|
||||||
if ($('iframe[src^="https://www.youtube.com/embed/"]').length) {
|
|
||||||
$Body.append('<script src="https://www.youtube.com/iframe_api"></script>');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static updateLocation(url) {
|
|
||||||
let location = url || W.location.href;
|
|
||||||
location = location.replace(W.URLDetails['base'], '/');
|
|
||||||
const hash = location.indexOf('#');
|
|
||||||
|
|
||||||
W.URLDetails.relative = location.split('#')[0];
|
|
||||||
W.URLDetails.hash = (hash >= 0) ? location.substr(location.indexOf('#')) : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// show site-wide alert
|
|
||||||
static alert(msg, cls) {
|
|
||||||
$SiteWideMessage.fadeOut('fast');
|
|
||||||
|
|
||||||
$SiteWideMessage.html(`<div class="page-alert"><div class="alert alert-${cls}"><i class="close" data-dismiss="alert">×</i>${msg}</div></div>`);
|
|
||||||
$SiteWideMessage.find('.page-alert').alert();
|
|
||||||
|
|
||||||
$SiteWideMessage.find('.close[data-dismiss="alert"]').click(() => {
|
|
||||||
$SiteWideMessage.fadeOut('slow', () => {
|
|
||||||
$SiteWideMessage.find('.page-alert').alert('close');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$SiteWideMessage.fadeIn('slow');
|
|
||||||
|
|
||||||
if ($AlertNotify.length) {
|
|
||||||
$AlertNotify[0].play();
|
|
||||||
}
|
|
||||||
|
|
||||||
$(W).trigger('alert-appeared');
|
|
||||||
}
|
|
||||||
|
|
||||||
// hide site-wide alert
|
|
||||||
static alertHide() {
|
|
||||||
if ($SiteWideMessage.length !== 0) {
|
|
||||||
$SiteWideMessage.fadeOut('slow', () => {
|
|
||||||
$SiteWideMessage.find('.alert').alert('close');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
$AlertNotify.length &&
|
|
||||||
typeof $AlertNotify[0].stop !== 'undefined'
|
|
||||||
) {
|
|
||||||
$AlertNotify[0].stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
$(W).trigger('alert-removed');
|
|
||||||
}
|
|
||||||
|
|
||||||
// load all images
|
|
||||||
static loadImages() {
|
|
||||||
const $imgs = $Body.find('img');
|
|
||||||
const $imgUrls = [];
|
|
||||||
const $imgLazyUrls = [];
|
|
||||||
|
|
||||||
// collect image details
|
|
||||||
$imgs.each((i, el) => {
|
|
||||||
const $el = $(el);
|
|
||||||
const src = $el.attr('src');
|
|
||||||
const lazySrc = $el.data('lazy-src');
|
|
||||||
|
|
||||||
if (src && src.length) {
|
|
||||||
$imgUrls.push(src);
|
|
||||||
}
|
|
||||||
if (lazySrc && lazySrc.length) {
|
|
||||||
$imgLazyUrls.push(lazySrc);
|
|
||||||
$el.addClass('loading');
|
|
||||||
|
|
||||||
AjaxUI.preload([lazySrc]).then(() => {
|
|
||||||
$el.attr('src', lazySrc);
|
|
||||||
|
|
||||||
$el.addClass('loaded');
|
|
||||||
$el.removeClass('loading');
|
|
||||||
|
|
||||||
$el.trigger('image-lazy-loaded');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// load defined images
|
|
||||||
AjaxUI.preload($imgUrls).then(() => {
|
|
||||||
$(W).trigger('images-loaded');
|
|
||||||
|
|
||||||
// load lazy images
|
|
||||||
AjaxUI.preload($imgLazyUrls).then(() => {
|
|
||||||
console.log('All images are loaded!');
|
|
||||||
|
|
||||||
$(W).trigger('images-lazy-loaded');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static dispose() {
|
|
||||||
console.log(`Destroying: ${NAME}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$(W).on(`${Events.AJAX} ${Events.LOADED}`, () => {
|
|
||||||
MainUI.init();
|
|
||||||
});
|
|
||||||
|
|
||||||
$(W).on('beforeunload', () => {
|
|
||||||
Spinner.show(() => {
|
|
||||||
$Body.removeClass('loaded');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
W.MainUI = MainUI;
|
|
||||||
|
|
||||||
return MainUI;
|
|
||||||
})($);
|
|
||||||
|
|
||||||
export default MainUI;
|
|
@ -1,3 +1,5 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
import '../scss/app.scss';
|
import '../scss/app.scss';
|
||||||
|
|
||||||
// import Bootstrap
|
// import Bootstrap
|
||||||
@ -7,7 +9,21 @@ import 'bootstrap/js/dist/alert';
|
|||||||
import 'bootstrap/js/dist/button';
|
import 'bootstrap/js/dist/button';
|
||||||
import 'bootstrap/js/dist/carousel';
|
import 'bootstrap/js/dist/carousel';
|
||||||
import 'bootstrap/js/dist/collapse';
|
import 'bootstrap/js/dist/collapse';
|
||||||
import 'bootstrap/js/dist/dropdown';
|
|
||||||
|
import 'hammerjs/hammer';
|
||||||
|
import 'jquery-hammerjs/jquery.hammer';
|
||||||
|
|
||||||
|
// Routie
|
||||||
|
//import 'pouchdb/dist/pouchdb';
|
||||||
|
//import 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/routes/index';
|
||||||
|
|
||||||
|
// conflicts with _components/_ui.hover.js (shows dropdown on hover)
|
||||||
|
//import 'bootstrap/js/dist/dropdown';
|
||||||
|
import 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.hover';
|
||||||
|
|
||||||
|
import 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.carousel';
|
||||||
|
import 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.menu';
|
||||||
|
|
||||||
import 'bootstrap/js/dist/modal';
|
import 'bootstrap/js/dist/modal';
|
||||||
import 'bootstrap/js/dist/tooltip';
|
import 'bootstrap/js/dist/tooltip';
|
||||||
import 'bootstrap/js/dist/popover';
|
import 'bootstrap/js/dist/popover';
|
||||||
@ -22,12 +38,38 @@ import 'bootstrap/js/dist/tab';
|
|||||||
// Uncomment it to enable meta-lightbox zooming on hover
|
// Uncomment it to enable meta-lightbox zooming on hover
|
||||||
//import 'jquery-zoom/jquery.zoom';
|
//import 'jquery-zoom/jquery.zoom';
|
||||||
|
|
||||||
// youtube video preview image
|
|
||||||
import './_components/_ui.video.preview';
|
|
||||||
|
|
||||||
|
// Toggle bootstrap form fields
|
||||||
|
//import FormToggleUI from 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.fields.toggle';
|
||||||
|
|
||||||
|
// Bootstrap Date & Time fields
|
||||||
|
//import FormDatetime from 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.datetime';
|
||||||
|
|
||||||
|
// Stepped forms functionality
|
||||||
|
//import FormStepped from 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.stepped';
|
||||||
|
|
||||||
|
// Forms validation functionality
|
||||||
|
//import FormValidate from 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.validate';
|
||||||
|
|
||||||
|
// Store forms data into localStorage
|
||||||
|
//import FormStorage from 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.storage';
|
||||||
|
|
||||||
|
// client-side images cropping
|
||||||
|
//import FormCroppie from 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.form.croppie';
|
||||||
|
|
||||||
|
// Google NoCaptcha fields
|
||||||
|
//import NoCaptcha from 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.nocaptcha';
|
||||||
|
|
||||||
|
// youtube video preview image
|
||||||
|
import 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.video.preview';
|
||||||
|
|
||||||
|
// Meta Lightbox
|
||||||
import 'meta-lightbox/meta-lightbox';
|
import 'meta-lightbox/meta-lightbox';
|
||||||
|
|
||||||
import './_main';
|
//import Confirmation from 'bootstrap-confirmation2/dist/bootstrap-confirmation';
|
||||||
|
//import Table from 'bootstrap-table/dist/bootstrap-table';
|
||||||
|
|
||||||
|
import 'ss-bootstrap-ui-webpack-boilerplate/src/js/_main';
|
||||||
import './_layout';
|
import './_layout';
|
||||||
|
|
||||||
function importAll(r) {
|
function importAll(r) {
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
/**
|
|
||||||
* Add your global events here
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
en: {
|
|
||||||
jsSteppedForm: {
|
|
||||||
STEPCOUNTER: '<div class="steps-counter">Step <b class="current-step"></b> of <b class="total-steps"></b></div>',
|
|
||||||
STEPBUTTONS: '<div class="steps-buttons">' +
|
|
||||||
'<a href="#" class="step-ctrl step-prev"><i class="fas fa-chevron-left"></i> Prev</a>' +
|
|
||||||
' <a href="#" class="step-ctrl step-next">Next <i class="fas fa-chevron-right"></i></a>' +
|
|
||||||
'</div>',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
@ -1 +1,3 @@
|
|||||||
import '../_components/_ui.map.api';
|
"use strict";
|
||||||
|
|
||||||
|
import 'ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.map.api';
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
// Bootstrap
|
|
||||||
@import "~bootstrap/scss/root";
|
|
||||||
@import "~bootstrap/scss/reboot";
|
|
||||||
@import "~bootstrap/scss/type";
|
|
||||||
@import "~bootstrap/scss/images";
|
|
||||||
@import "~bootstrap/scss/code";
|
|
||||||
@import "~bootstrap/scss/grid";
|
|
||||||
@import "~bootstrap/scss/tables";
|
|
||||||
@import "~bootstrap/scss/forms";
|
|
||||||
@import "~bootstrap/scss/buttons";
|
|
||||||
@import "~bootstrap/scss/transitions";
|
|
||||||
@import "~bootstrap/scss/dropdown";
|
|
||||||
@import "~bootstrap/scss/button-group";
|
|
||||||
@import "~bootstrap/scss/input-group";
|
|
||||||
@import "~bootstrap/scss/custom-forms";
|
|
||||||
@import "~bootstrap/scss/nav";
|
|
||||||
@import "~bootstrap/scss/navbar";
|
|
||||||
@import "~bootstrap/scss/card";
|
|
||||||
@import "~bootstrap/scss/breadcrumb";
|
|
||||||
@import "~bootstrap/scss/pagination";
|
|
||||||
@import "~bootstrap/scss/badge";
|
|
||||||
@import "~bootstrap/scss/jumbotron";
|
|
||||||
@import "~bootstrap/scss/alert";
|
|
||||||
@import "~bootstrap/scss/progress";
|
|
||||||
@import "~bootstrap/scss/media";
|
|
||||||
@import "~bootstrap/scss/list-group";
|
|
||||||
@import "~bootstrap/scss/close";
|
|
||||||
@import "~bootstrap/scss/modal";
|
|
||||||
@import "~bootstrap/scss/tooltip";
|
|
||||||
@import "~bootstrap/scss/popover";
|
|
||||||
@import "~bootstrap/scss/carousel";
|
|
||||||
@import "~bootstrap/scss/utilities";
|
|
||||||
@import "~bootstrap/scss/print";
|
|
||||||
|
|
||||||
@import "_ui.carousel";
|
|
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* Bootstrap carousel improvement
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*.carousel-item {
|
|
||||||
&.active {
|
|
||||||
display: flex !important;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
.carousel-slide {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: flex-start;
|
|
||||||
|
|
||||||
.video {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
iframe {
|
|
||||||
width: 100% !important;
|
|
||||||
height: auto !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.img {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel-control-prev,
|
|
||||||
.carousel-control-next {
|
|
||||||
z-index: 2;
|
|
||||||
font-size: 3rem;
|
|
||||||
text-shadow: 1px 1px #000;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
background: rgba(0, 0, 0, 0.6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel-indicators li {
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
// 1px 1px #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel-title {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.carousel-title,
|
|
||||||
.carousel-content {
|
|
||||||
text-shadow: 1px 1px #000;
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Basic styles for silverstripe-elemental
|
|
||||||
*/
|
|
||||||
|
|
||||||
// hide default page title cuz elemental object will be used to display titles
|
|
||||||
h1.page-header {
|
|
||||||
display: none;
|
|
||||||
|
|
||||||
&.no-elements {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add top/bottom paddings for basic elements
|
|
||||||
.page-content > .element {
|
|
||||||
position: relative;
|
|
||||||
padding: ($grid-gutter-height / 2) 0;
|
|
||||||
|
|
||||||
// remove paddings of the slideshow
|
|
||||||
&.dynamic__elements__image__elements__elementimage,
|
|
||||||
&.site__elements__sliderelement {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove container paddings for the slideshow
|
|
||||||
.dynamic__elements__image__elements__elementimage,
|
|
||||||
.site__elements__sliderelement {
|
|
||||||
.container-fluid {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add top/bottom paddings for basic Include/Content.ss forms
|
|
||||||
.page-content > .form-container {
|
|
||||||
position: relative;
|
|
||||||
padding: ($grid-gutter-height / 2) 0;
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
$fa-font-path: "~font-awesome/fonts";
|
|
||||||
|
|
||||||
@import "~font-awesome/scss/font-awesome";
|
|
@ -1,39 +0,0 @@
|
|||||||
// date-time fields
|
|
||||||
input.date,
|
|
||||||
input.time {
|
|
||||||
&[readonly] {
|
|
||||||
background-color: $white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bootstrap-timepicker-widget,
|
|
||||||
.datepicker-dropdown {
|
|
||||||
border: 1px solid #ced4da;
|
|
||||||
box-shadow: 0 0 3px #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bootstrap-timepicker-widget {
|
|
||||||
.glyphicon {
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
display: inline-block;
|
|
||||||
font-style: normal;
|
|
||||||
font-variant: normal;
|
|
||||||
text-rendering: auto;
|
|
||||||
line-height: 1;
|
|
||||||
font-family: Font Awesome\ 5 Free;
|
|
||||||
font-weight: 900;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glyphicon-chevron-up:before {
|
|
||||||
content: "\f077";
|
|
||||||
}
|
|
||||||
|
|
||||||
.glyphicon-chevron-down:before {
|
|
||||||
content: "\f078";
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
border: 1px solid #ced4da;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
.form-stepped {
|
|
||||||
.step {
|
|
||||||
display: none;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
$lightbox-breakpoint: map-get($grid-breakpoints, "sm");
|
|
||||||
$lightbox-link-hover-color: $link-hover-color;
|
|
||||||
|
|
||||||
@import "~meta-lightbox/scss/meta-lightbox";
|
|
||||||
@import "~meta-lightbox/scss/meta-lightbox-theme";
|
|
@ -1,309 +0,0 @@
|
|||||||
/*
|
|
||||||
* some basic styles
|
|
||||||
*/
|
|
||||||
|
|
||||||
// don't let images be wider than the parent layer
|
|
||||||
iframe,
|
|
||||||
img {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.a {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.a:hover,
|
|
||||||
.a:focus,
|
|
||||||
a:hover,
|
|
||||||
a:focus,
|
|
||||||
[data-toggle]:hover,
|
|
||||||
[data-toggle]:focus {
|
|
||||||
opacity: .8;
|
|
||||||
|
|
||||||
.fas,
|
|
||||||
.fab,
|
|
||||||
&.fas,
|
|
||||||
&.fab {
|
|
||||||
transform: rotate(-180deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-toggle="collapse"] {
|
|
||||||
&[aria-expanded="true"] {
|
|
||||||
.accordion-icon {
|
|
||||||
&:before {
|
|
||||||
content: "\f068";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// transactions
|
|
||||||
.transition,
|
|
||||||
a, a *,
|
|
||||||
.a, .a *,
|
|
||||||
button, input, optgroup, select, textarea,
|
|
||||||
.btn,
|
|
||||||
.alert,
|
|
||||||
.dropdown,
|
|
||||||
[data-toggle], [data-toggle] *,
|
|
||||||
.container,
|
|
||||||
.container-fluid,
|
|
||||||
.row,
|
|
||||||
[class="col-*"] {
|
|
||||||
transition: all 0.4s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-toolbar {
|
|
||||||
margin-top: $grid-gutter-height / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.field {
|
|
||||||
position: relative;
|
|
||||||
margin: ($grid-gutter-height / 4) 0;
|
|
||||||
|
|
||||||
&.composite {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.required {
|
|
||||||
&:after {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
top: 2rem;
|
|
||||||
right: .5rem;
|
|
||||||
content: "*";
|
|
||||||
color: $red;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.holder-error,
|
|
||||||
&.error {
|
|
||||||
input, select, textarea {
|
|
||||||
border-color: $red;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
color: $red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn) {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.message {
|
|
||||||
@extend .alert;
|
|
||||||
|
|
||||||
@extend .alert-info;
|
|
||||||
|
|
||||||
display: block;
|
|
||||||
margin: .5rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message.validation,
|
|
||||||
.message.required,
|
|
||||||
.message.error {
|
|
||||||
@extend .alert;
|
|
||||||
|
|
||||||
@extend .alert-danger;
|
|
||||||
}
|
|
||||||
|
|
||||||
// element col paddings
|
|
||||||
.col-block {
|
|
||||||
padding: $grid-gutter-height / 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// rewrite btn opacity on hover
|
|
||||||
.btn {
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SS-messages
|
|
||||||
.message {
|
|
||||||
@extend .alert;
|
|
||||||
|
|
||||||
@extend .alert-info;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message.required,
|
|
||||||
.message.error {
|
|
||||||
@extend .alert;
|
|
||||||
|
|
||||||
@extend .alert-danger;
|
|
||||||
}
|
|
||||||
|
|
||||||
// dropdown icon
|
|
||||||
.dropdown.show .dropdown-toggle::after,
|
|
||||||
.dropdown-toggle.active-dropdown::after,
|
|
||||||
.dropdown-toggle.active::after {
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// dropdown hover
|
|
||||||
/*
|
|
||||||
.dropdown.show {
|
|
||||||
.dropdown {
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
.dropdown-menu {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media only screen and (min-width: map-get($grid-breakpoints, "md")) {
|
|
||||||
.dropdown-hover ul li {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-hover ul li {
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
> .dropdown-toggle::after {
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
> ul {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-hover ul ul {
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
left: 0;
|
|
||||||
min-width: 250px;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-hover ul ul li {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-hover ul ul li {
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
> ul {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-hover ul ul ul {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 100%;
|
|
||||||
min-width: 250px;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-hover ul ul ul li {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-hover ul ul ul li {
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
ul {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-hover ul ul ul ul {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: -100%;
|
|
||||||
min-width: 250px;
|
|
||||||
display: none;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// dark dropdowns
|
|
||||||
.navbar-dark {
|
|
||||||
.nav-link {
|
|
||||||
@include hover-focus {
|
|
||||||
background: $navbar-dark-hover-background;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.active > .nav-link,
|
|
||||||
.nav-link.active {
|
|
||||||
background: $navbar-dark-active-background;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-link.show,
|
|
||||||
.navbar-nav .show > .nav-link {
|
|
||||||
background: $navbar-dark-show-background;
|
|
||||||
color: $navbar-dark-show-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-menu.bg-dark {
|
|
||||||
border-color: $dark;
|
|
||||||
|
|
||||||
.nav-link {
|
|
||||||
color: $navbar-dark-color;
|
|
||||||
|
|
||||||
@include hover-focus {
|
|
||||||
color: $navbar-dark-hover-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
&.disabled {
|
|
||||||
color: $navbar-dark-disabled-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.show > .nav-link,
|
|
||||||
.active > .nav-link,
|
|
||||||
.nav-link.show,
|
|
||||||
.nav-link.active {
|
|
||||||
color: $navbar-dark-active-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-item {
|
|
||||||
@include hover-focus {
|
|
||||||
color: $navbar-dark-hover-color;
|
|
||||||
background: $navbar-dark-hover-background;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
&.active,
|
|
||||||
&:active {
|
|
||||||
background: $navbar-dark-active-background;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-link {
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pulse
|
|
||||||
.pulse {
|
|
||||||
animation: pulse 0.8s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pulse {
|
|
||||||
0% {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
50% {
|
|
||||||
transform: scale(0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
@import "../variables";
|
|
||||||
@import "~mapbox-gl/dist/mapbox-gl.css";
|
|
||||||
|
|
||||||
.mapAPI-map {
|
|
||||||
height: 30rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mapboxgl-popup-content {
|
|
||||||
box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.4);
|
|
||||||
|
|
||||||
.mapboxgl-popup-close-button {
|
|
||||||
font-size: 2rem;
|
|
||||||
padding: .5rem;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
background: $primary;
|
|
||||||
color: $white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mapboxgl-marker {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
font-size: 30px;
|
|
||||||
cursor: pointer;
|
|
||||||
text-align: center;
|
|
||||||
color: $primary;
|
|
||||||
|
|
||||||
.fas {
|
|
||||||
animation: pulse 0.8s linear infinite;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
.cart-footer {
|
|
||||||
margin-top: $grid-gutter-height / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.address-panel,
|
|
||||||
.account-nav {
|
|
||||||
margin-bottom: $grid-gutter-height / 2;
|
|
||||||
}
|
|
@ -7,6 +7,8 @@ $container-max-widths: (sm: 540px, md: 720px, lg: 960px, xl: 1140px, xxl: 1330px
|
|||||||
|
|
||||||
$font-family-base: "Lato", sans-serif;
|
$font-family-base: "Lato", sans-serif;
|
||||||
|
|
||||||
|
$grid-gutter-width: 30px;
|
||||||
|
$grid-gutter-xs-width: $grid-gutter-width / 2;
|
||||||
$grid-gutter-height: 8rem;
|
$grid-gutter-height: 8rem;
|
||||||
|
|
||||||
$gray-900: #212529;
|
$gray-900: #212529;
|
||||||
@ -47,3 +49,4 @@ $enable-flex: true;
|
|||||||
@import "~bootstrap/scss/functions";
|
@import "~bootstrap/scss/functions";
|
||||||
@import "~bootstrap/scss/variables";
|
@import "~bootstrap/scss/variables";
|
||||||
@import "~bootstrap/scss/mixins";
|
@import "~bootstrap/scss/mixins";
|
||||||
|
@import "~ss-bootstrap-ui-webpack-boilerplate/src/scss/_components/_variables";
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
//@import "~bootstrap-select/sass/bootstrap-select.scss";
|
//@import "~bootstrap-select/sass/bootstrap-select.scss";
|
||||||
|
|
||||||
@import "~bootstrap-datepicker/dist/css/bootstrap-datepicker.css";
|
//@import "~bootstrap-datepicker/dist/css/bootstrap-datepicker.css";
|
||||||
@import "~bootstrap-timepicker/css/bootstrap-timepicker.css";
|
//@import "~bootstrap-timepicker/css/bootstrap-timepicker.css";
|
||||||
|
|
||||||
// Your custom variables
|
// Your custom variables
|
||||||
@import "_variables";
|
@import "_variables";
|
||||||
|
|
||||||
@import "_components/_ui.bootstrap";
|
@import "~ss-bootstrap-ui-webpack-boilerplate/src/scss/_components/_ui.bootstrap";
|
||||||
|
|
||||||
// By default we prefer font awesome CDN
|
// By default we prefer font awesome CDN
|
||||||
//@import "_components/_ui.fontawesome";
|
//@import "~ss-bootstrap-ui-webpack-boilerplate/src/js/_components/_ui.fontawesome";
|
||||||
@import "_components/_ui.lightbox";
|
@import "~ss-bootstrap-ui-webpack-boilerplate/src/scss/_components/_ui.lightbox";
|
||||||
|
|
||||||
@import "_components/_ui.main";
|
@import "~ss-bootstrap-ui-webpack-boilerplate/src/scss/_components/_ui.main";
|
||||||
@import "_components/_ui.form.basics";
|
@import "~ss-bootstrap-ui-webpack-boilerplate/src/scss/_components/_ui.form.basics";
|
||||||
@import "_components/_ui.elemental";
|
@import "~ss-bootstrap-ui-webpack-boilerplate/src/scss/_components/_ui.elemental";
|
||||||
|
|
||||||
// Your custom styling
|
// Your custom styling
|
||||||
@import "_typography";
|
@import "_typography";
|
||||||
|
@ -1,59 +1,3 @@
|
|||||||
@import "../_variables";
|
@import "../_variables";
|
||||||
|
|
||||||
@import "~bootstrap/scss/tables";
|
@import "~ss-bootstrap-ui-webpack-boilerplate/src/scss/types/editor";
|
||||||
|
|
||||||
.image {
|
|
||||||
&.left {
|
|
||||||
float: left;
|
|
||||||
clear: left;
|
|
||||||
margin: 0 1rem 1rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.center {
|
|
||||||
display: block;
|
|
||||||
margin: 1rem auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.right {
|
|
||||||
float: right;
|
|
||||||
clear: right;
|
|
||||||
margin: 1rem 0 0 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-left {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-center {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-right {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-justify {
|
|
||||||
text-align: justify;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
border-collapse: collapse;
|
|
||||||
|
|
||||||
@extend .table;
|
|
||||||
|
|
||||||
@extend .table-bordered;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
&.table-none {
|
|
||||||
border: 0;
|
|
||||||
|
|
||||||
tr, td, th {
|
|
||||||
border: 0;
|
|
||||||
background: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,163 +1,3 @@
|
|||||||
@import "../_variables";
|
@import "../_variables";
|
||||||
|
|
||||||
h1.title {
|
@import "~ss-bootstrap-ui-webpack-boilerplate/src/scss/types/order";
|
||||||
display: block;
|
|
||||||
text-align: right;
|
|
||||||
border-bottom: 1px solid $border-color;
|
|
||||||
text-transform: uppercase;
|
|
||||||
line-height: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.warningMessage {
|
|
||||||
position: relative;
|
|
||||||
padding: $alert-padding-y $alert-padding-x;
|
|
||||||
margin-bottom: $alert-margin-bottom;
|
|
||||||
border: $alert-border-width solid transparent;
|
|
||||||
|
|
||||||
@include border-radius($alert-border-radius);
|
|
||||||
|
|
||||||
color: #856404;
|
|
||||||
background-color: #fff3cd;
|
|
||||||
border-color: #ffeeba;
|
|
||||||
}
|
|
||||||
|
|
||||||
#Content {
|
|
||||||
text-align: left;
|
|
||||||
margin: auto;
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#Content td {}
|
|
||||||
|
|
||||||
#Content .emailTitle {
|
|
||||||
font-family: $font-family-base;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: $h1-font-size;
|
|
||||||
}
|
|
||||||
|
|
||||||
#Content .PageTitle {
|
|
||||||
padding: 5px;
|
|
||||||
color: $body-color;
|
|
||||||
font-size: 14px;
|
|
||||||
font-family: $font-family-base;
|
|
||||||
}
|
|
||||||
|
|
||||||
#Content .footer td {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#Content .footer td.right {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
#Content .typography {
|
|
||||||
padding: 0px 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#Content .typography a {
|
|
||||||
font-size: 1em;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
#Content .typography a:hover {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#Content .typography ul {
|
|
||||||
padding: 2px 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#Content .typography ul li {
|
|
||||||
padding: 2px 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#Content .typography p {
|
|
||||||
margin: 0.75em 0em;
|
|
||||||
color: $body-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
table#SenderTable .sender,
|
|
||||||
table#SenderTable .meta {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
table#MetaTable {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
table#MetaTable .label {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ShippingTable td,
|
|
||||||
#ShippingTable th {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.infotable {
|
|
||||||
border: 1px solid $border-color;
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 100%;
|
|
||||||
border-top: 1px solid $border-color;
|
|
||||||
border-bottom: 1px solid $border-color;
|
|
||||||
background: $body-bg;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.infotable td.product.title {
|
|
||||||
color: $link-color;
|
|
||||||
font-size: $h3-font-size;
|
|
||||||
font-weight: normal;
|
|
||||||
font-family: $font-family-base;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.infotable tr td,
|
|
||||||
table.infotable tr th {
|
|
||||||
padding: 5px;
|
|
||||||
color: $body-color;
|
|
||||||
border: 1px solid $border-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.infotable td {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.infotable tr.summary {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.infotable td.ordersummary {
|
|
||||||
font-size: 1em;
|
|
||||||
border-bottom: 1px solid $border-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.infotable tr th {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.infotable tr td a {
|
|
||||||
color: $link-color;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.infotable tr td a:hover {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.infotable .modifierRow,
|
|
||||||
table.infotable .threeColHeader {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.infotable .right {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.infotable .center {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.infotable .left,
|
|
||||||
table.infotable th {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
19
app/src/Extensions/BlogExtension.php
Normal file
19
app/src/Extensions/BlogExtension.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Site\Extensions;
|
||||||
|
|
||||||
|
use SilverStripe\Blog\Forms\GridField\GridFieldConfigBlogPost;
|
||||||
|
use SilverStripe\Forms\FieldList;
|
||||||
|
use SilverStripe\ORM\DataExtension;
|
||||||
|
|
||||||
|
class BlogExtension extends DataExtension
|
||||||
|
{
|
||||||
|
public function updateCMSFields(FieldList $fields)
|
||||||
|
{
|
||||||
|
$f = $fields->dataFieldByName('ChildPages');
|
||||||
|
if ($f) {
|
||||||
|
$f->setConfig(GridFieldConfigBlogPost::create(100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,7 @@ use SilverStripe\ORM\DataExtension;
|
|||||||
|
|
||||||
class ElementContentWidget extends DataExtension
|
class ElementContentWidget extends DataExtension
|
||||||
{
|
{
|
||||||
private static $db = [
|
/*private static $db = [
|
||||||
'BlockIcon' => 'Varchar(255)',
|
'BlockIcon' => 'Varchar(255)',
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -32,5 +32,5 @@ class ElementContentWidget extends DataExtension
|
|||||||
FontAwesomeField::create('BlockIcon'),
|
FontAwesomeField::create('BlockIcon'),
|
||||||
LinkField::create('BlockLinkID', 'Link'),
|
LinkField::create('BlockLinkID', 'Link'),
|
||||||
]);
|
]);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,17 @@ class EmbedObjectField extends EmbeddedObjectField
|
|||||||
CheckboxField::create(
|
CheckboxField::create(
|
||||||
$name . '[autoplay]',
|
$name . '[autoplay]',
|
||||||
_t(self::CLASS.'AUTOPLAY', 'Autoplay video?')
|
_t(self::CLASS.'AUTOPLAY', 'Autoplay video?')
|
||||||
)->setValue($this->object->Autoplay),
|
)->setValue($this->object->getField('Autoplay')),
|
||||||
|
|
||||||
CheckboxField::create(
|
CheckboxField::create(
|
||||||
$name . '[loop]',
|
$name . '[loop]',
|
||||||
_t(self::CLASS.'LOOP', 'Loop video?')
|
_t(self::CLASS.'LOOP', 'Loop video?')
|
||||||
)->setValue($this->object->Loop)
|
)->setValue($this->object->getField('Loop')),
|
||||||
|
|
||||||
|
CheckboxField::create(
|
||||||
|
$name.'[controls]',
|
||||||
|
_t(self::CLASS.'CONTROLS', 'Show player controls?')
|
||||||
|
)->setValue($this->object->getField('Controls'))
|
||||||
];
|
];
|
||||||
|
|
||||||
return CompositeField::create(array_merge([
|
return CompositeField::create(array_merge([
|
||||||
|
@ -11,6 +11,7 @@ class EmbeddedObjectExtension extends DataExtension
|
|||||||
private static $db = [
|
private static $db = [
|
||||||
'Autoplay' => 'Boolean(0)',
|
'Autoplay' => 'Boolean(0)',
|
||||||
'Loop' => 'Boolean(0)',
|
'Loop' => 'Boolean(0)',
|
||||||
|
'Controls' => 'Boolean(1)',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function Embed()
|
public function Embed()
|
||||||
@ -34,13 +35,14 @@ class EmbeddedObjectExtension extends DataExtension
|
|||||||
'modestbranding=1',
|
'modestbranding=1',
|
||||||
'rel=0',
|
'rel=0',
|
||||||
'showinfo=0',
|
'showinfo=0',
|
||||||
|
'controls='.($this->owner->getField('Controls') ? '1': '0'),
|
||||||
], $params);
|
], $params);
|
||||||
|
|
||||||
if ($this->owner->Autoplay) {
|
if ($this->owner->getField('Autoplay')) {
|
||||||
$params[] = 'autoplay=1';
|
$params[] = 'autoplay=1';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->owner->Loop) {
|
if ($this->owner->getField('Loop')) {
|
||||||
$params[] = 'loop=1';
|
$params[] = 'loop=1';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Site\Extensions;
|
namespace Site\Extensions;
|
||||||
|
|
||||||
|
use A2nt\SilverStripeMapboxField\MapboxField;
|
||||||
use Innoweb\Sitemap\Pages\SitemapPage;
|
use Innoweb\Sitemap\Pages\SitemapPage;
|
||||||
use SilverStripe\AssetAdmin\Forms\UploadField;
|
use SilverStripe\AssetAdmin\Forms\UploadField;
|
||||||
use SilverStripe\Assets\Image;
|
use SilverStripe\Assets\Image;
|
||||||
@ -13,8 +14,8 @@ use SilverStripe\CMS\Model\SiteTree;
|
|||||||
use SilverStripe\Forms\FieldList;
|
use SilverStripe\Forms\FieldList;
|
||||||
use SilverStripe\Forms\TreeMultiselectField;
|
use SilverStripe\Forms\TreeMultiselectField;
|
||||||
use SilverStripe\Forms\DropdownField;
|
use SilverStripe\Forms\DropdownField;
|
||||||
|
|
||||||
//use BetterBrief\GoogleMapField;
|
//use BetterBrief\GoogleMapField;
|
||||||
use Bigfork\SilverStripeMapboxField\MapboxField;
|
|
||||||
|
|
||||||
class SiteConfigExtension extends DataExtension
|
class SiteConfigExtension extends DataExtension
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,7 @@ class SiteTreeExtension extends DataExtension
|
|||||||
'ExtraCode' => 'Text',
|
'ExtraCode' => 'Text',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function updateCMSFields(FieldList $fields)
|
public function updateSettingsFields(FieldList $fields)
|
||||||
{
|
{
|
||||||
$fields->addFieldsToTab('Root.Settings', [
|
$fields->addFieldsToTab('Root.Settings', [
|
||||||
TextareaField::create(
|
TextareaField::create(
|
||||||
|
@ -6,4 +6,5 @@ use Page;
|
|||||||
|
|
||||||
class HomePage extends Page
|
class HomePage extends Page
|
||||||
{
|
{
|
||||||
|
private static $icon_class = 'font-icon-p-home';
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,14 @@
|
|||||||
|
|
||||||
namespace Site\Pages;
|
namespace Site\Pages;
|
||||||
|
|
||||||
|
|
||||||
use SilverStripe\Forms\GridField\GridField;
|
use SilverStripe\Forms\GridField\GridField;
|
||||||
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
|
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
|
||||||
use Site\Models\TeamMember;
|
use Site\Models\TeamMember;
|
||||||
|
|
||||||
class TeamPage extends \Page
|
class TeamPage extends \Page
|
||||||
{
|
{
|
||||||
|
private static $icon_class = 'font-icon-p-profile';
|
||||||
|
|
||||||
private static $has_many = [
|
private static $has_many = [
|
||||||
'Members' => TeamMember::class,
|
'Members' => TeamMember::class,
|
||||||
];
|
];
|
||||||
|
78
app/src/Tasks/BuildTask.php
Normal file
78
app/src/Tasks/BuildTask.php
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Site\Tasks;
|
||||||
|
|
||||||
|
|
||||||
|
use SilverStripe\Control\HTTPRequest;
|
||||||
|
|
||||||
|
class BuildTask extends \SilverStripe\Dev\BuildTask
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $title = 'Base build task interface';
|
||||||
|
protected $description = 'Base build task interface';
|
||||||
|
protected $enabled = false;
|
||||||
|
|
||||||
|
protected $messages = [];
|
||||||
|
/**
|
||||||
|
* Implement this method in the task subclass to
|
||||||
|
* execute via the TaskRunner
|
||||||
|
*
|
||||||
|
* @param HTTPRequest $request
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public function run($request)
|
||||||
|
{
|
||||||
|
// TODO: Implement run() method.
|
||||||
|
return $this->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function Title()
|
||||||
|
{
|
||||||
|
return $this->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setMessage($msg, string $type = 'msg')
|
||||||
|
{
|
||||||
|
if(is_array($msg)) {
|
||||||
|
$type = 'list';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->messages[] = [$type, $msg];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
echo '<style>'
|
||||||
|
.'.info{color:#053bff}'
|
||||||
|
.'.bad,.error{color:red}'
|
||||||
|
.'.good,.success{color:green}'
|
||||||
|
.'</style>';
|
||||||
|
|
||||||
|
foreach ($this->messages as $item) {
|
||||||
|
$type = $item[0];
|
||||||
|
$msg = $item[1];
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case 'h2':
|
||||||
|
echo '<h2>'.$msg.'</h2>'.PHP_EOL;
|
||||||
|
break;
|
||||||
|
case 'h3':
|
||||||
|
echo '<h3>'.$msg.'</h3>'.PHP_EOL;
|
||||||
|
break;
|
||||||
|
case 'list':
|
||||||
|
echo '<ul>';
|
||||||
|
foreach ($msg as $m) {
|
||||||
|
echo '<li>'.$m.'</li>';
|
||||||
|
}
|
||||||
|
echo '</ul>';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
echo $msg.'<br/>'.PHP_EOL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '<h2 class="success">Success!</h2>';
|
||||||
|
}
|
||||||
|
}
|
47
app/src/Tasks/RestoreFilesTask.php
Normal file
47
app/src/Tasks/RestoreFilesTask.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Site\Tasks;
|
||||||
|
|
||||||
|
use SilverStripe\Assets\File;
|
||||||
|
use SilverStripe\Dev\BuildTask;
|
||||||
|
|
||||||
|
class RestoreFilesTask extends BuildTask
|
||||||
|
{
|
||||||
|
protected $title = 'Restore Files Task';
|
||||||
|
|
||||||
|
protected $description = 'Restores file from specific folder';
|
||||||
|
|
||||||
|
protected $enabled = false;
|
||||||
|
|
||||||
|
public function run($request)
|
||||||
|
{
|
||||||
|
die('Specify path first');
|
||||||
|
$path = '*<Path to the folder with files to be restored>*';
|
||||||
|
|
||||||
|
$files = array_diff(scandir($path), ['.','..']);
|
||||||
|
foreach ($files as $fileName) {
|
||||||
|
$file = File::get()->filter('Name', $fileName);
|
||||||
|
if (!$file->count()) {
|
||||||
|
echo '<b style="color:red">File name was not found at SS DB: '.$fileName.'</b><br/>'.PHP_EOL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($file as $f) {
|
||||||
|
if ($f->exists()) {
|
||||||
|
echo 'File #'.$f->ID.' already exists at SS file structure. <b style="color:green">'.$fileName.'</b><br/>' . PHP_EOL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo 'Found non existing at SS file system file and found it at SS DB.'
|
||||||
|
.' Creating the file #'.$f->ID.' at SS file system. "<b style="color:#053bff">' . $fileName . '"</b><br/>' . PHP_EOL;
|
||||||
|
|
||||||
|
$f->setFromLocalFile($path.'/'.$fileName);
|
||||||
|
$f->write();
|
||||||
|
$f->publishFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
die('Success!');
|
||||||
|
}
|
||||||
|
}
|
37
app/templates/Includes/SlideItem.ss
Normal file
37
app/templates/Includes/SlideItem.ss
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<% if $Video || $Image %>
|
||||||
|
<% if $Video %>
|
||||||
|
<div class="video">
|
||||||
|
$Video.EmbedHTML.RAW
|
||||||
|
</div>
|
||||||
|
<% else %>
|
||||||
|
<% if $PageLink %><a href="$PageLink.Link" title="$PageLink.MenuTitle.XML" class="btn-primary"><% end_if %>
|
||||||
|
|
||||||
|
<% if $Image %>
|
||||||
|
<span class="img">
|
||||||
|
<img class="d-block w-100" src="$Image.Fill(1200,600).URL" alt="<% if $Headline %>$Headline<% end_if %>">
|
||||||
|
</span>
|
||||||
|
<% end_if %>
|
||||||
|
<% if $PageLink %></a><% end_if %>
|
||||||
|
<% end_if %>
|
||||||
|
<% end_if %>
|
||||||
|
|
||||||
|
<% if $Content || $Headline || $Description || $PageLinkID %>
|
||||||
|
<div class="carousel-caption">
|
||||||
|
|
||||||
|
<div class="carousel-caption-container">
|
||||||
|
<% if $Headline %><h2 class="carousel-title">$Headline</h2><% end_if %>
|
||||||
|
<% if $Content %>
|
||||||
|
<div class="carousel-content typography">$Content</div>
|
||||||
|
<% else %>
|
||||||
|
<% if $Description %><p class="carousel-content">$Description</p><% end_if %>
|
||||||
|
<% end_if %>
|
||||||
|
<% if $PageLinkID %>
|
||||||
|
<p>
|
||||||
|
<a href="$PageLink.Link" title="$PageLink.MenuTitle.XML" class="btn btn-default btn-lg">
|
||||||
|
<i class="fas fa-bars"></i>
|
||||||
|
<%t Dynamic\FlexSlider\ORM\FlexSlider.LEARN_MORE "Learn more" %>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<% end_if %>
|
||||||
|
</div>
|
||||||
|
<% end_if %>
|
@ -18,7 +18,7 @@
|
|||||||
$Breadcrumbs
|
$Breadcrumbs
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
|
|
||||||
<% if $SideBarView || $Parent.SideBarView %>
|
<% if $SideBarView && $SideBar.Widgets.Count %>
|
||||||
<div class="$DefaultContainer">
|
<div class="$DefaultContainer">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
@ -26,11 +26,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<div class="page-content">
|
<div class="page-content">
|
||||||
<% if $SideBarView %>
|
|
||||||
$SideBarView
|
$SideBarView
|
||||||
<% else %>
|
|
||||||
$Parent.SideBarView
|
|
||||||
<% end_if %>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
<%-- BUGFIX: empty template file --%>
|
@ -13,53 +13,10 @@
|
|||||||
<div id="Carousel{$ID}" class="carousel slide js-carousel d-none d-sm-block"<% if $SlideShow.count > 1 %><% if $Interval %> data-interval="$Interval"<% end_if %> data-indicators="true" data-arrows="true"<% end_if %>>
|
<div id="Carousel{$ID}" class="carousel slide js-carousel d-none d-sm-block"<% if $SlideShow.count > 1 %><% if $Interval %> data-interval="$Interval"<% end_if %> data-indicators="true" data-arrows="true"<% end_if %>>
|
||||||
<div class="carousel-inner">
|
<div class="carousel-inner">
|
||||||
<% loop $SlideShow %>
|
<% loop $SlideShow %>
|
||||||
<div class="carousel-item carousel-item-{$SlideType}<% if $First %> active<% end_if %>">
|
<div class="carousel-item carousel-item-{$SlideType}<% if no $Controls %> carousel-item-nocontrols<% end_if %><% if $First %> active<% end_if %>">
|
||||||
|
|
||||||
|
|
||||||
<% if $Video || $Image %>
|
|
||||||
<div class="carousel-slide">
|
<div class="carousel-slide">
|
||||||
<% if $Video %>
|
<% include SlideItem %>
|
||||||
<div class="video">
|
|
||||||
$Video.EmbedHTML.RAW
|
|
||||||
</div>
|
</div>
|
||||||
<% end_if %>
|
|
||||||
|
|
||||||
<% if $PageLink %><a href="$PageLink.Link" title="$PageLink.MenuTitle.XML" class="btn-primary"><% end_if %>
|
|
||||||
|
|
||||||
<% if $Image %>
|
|
||||||
<span class="img">
|
|
||||||
<img class="d-block w-100" src="$Image.Fill(1200,600).URL" alt="<% if $Headline %>$Headline<% end_if %>">
|
|
||||||
</span>
|
|
||||||
<% end_if %>
|
|
||||||
<% if $PageLink %></a><% end_if %>
|
|
||||||
</div>
|
|
||||||
<% end_if %>
|
|
||||||
|
|
||||||
<% if $Content || $Headline || $Description || $PageLinkID %>
|
|
||||||
<% if not $Video && not $Image %>
|
|
||||||
<div class="carousel-slide">
|
|
||||||
<% else %>
|
|
||||||
<div class="carousel-caption">
|
|
||||||
<% end_if %>
|
|
||||||
|
|
||||||
<div class="carousel-caption-container">
|
|
||||||
<% if $Headline %><h2 class="carousel-title">$Headline</h2><% end_if %>
|
|
||||||
<% if $Content %>
|
|
||||||
<div class="carousel-content typography">$Content</div>
|
|
||||||
<% else %>
|
|
||||||
<% if $Description %><p class="carousel-content">$Description</p><% end_if %>
|
|
||||||
<% end_if %>
|
|
||||||
<% if $PageLinkID %>
|
|
||||||
<p>
|
|
||||||
<a href="$PageLink.Link" title="$PageLink.MenuTitle.XML" class="btn btn-default btn-lg">
|
|
||||||
<i class="fas fa-bars"></i>
|
|
||||||
<%t Dynamic\FlexSlider\ORM\FlexSlider.LEARN_MORE "Learn more" %>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<% end_if %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<% end_if %>
|
|
||||||
</div>
|
</div>
|
||||||
<% end_loop %>
|
<% end_loop %>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,7 +36,8 @@
|
|||||||
"silverstripe/environmentcheck": "*",
|
"silverstripe/environmentcheck": "*",
|
||||||
"silverstripe/widgets": "^2.0",
|
"silverstripe/widgets": "^2.0",
|
||||||
"a2nt/silverstripe-font-awesome-field": "dev-master",
|
"a2nt/silverstripe-font-awesome-field": "dev-master",
|
||||||
"a2nt/silverstripe-mapboxfield": "dev-master"
|
"a2nt/silverstripe-mapboxfield": "dev-master",
|
||||||
|
"bummzack/sortablefile": "*"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^5.7",
|
"phpunit/phpunit": "^5.7",
|
||||||
|
22
package.json
22
package.json
@ -15,7 +15,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "cross-env NODE_ENV=development webpack-dev-server --https -d --config webpack.config.dev.js",
|
"start": "cross-env NODE_ENV=development webpack-dev-server --https -d --config webpack.config.dev.js",
|
||||||
"dash": "cross-env NODE_ENV=development webpack-dashboard -- webpack-dev-server --config webpack.config.dev.js",
|
"dash": "cross-env NODE_ENV=development webpack-dashboard -- webpack-dev-server --config webpack.config.dev.js",
|
||||||
"prebuild": "rimraf build",
|
"prebuild": "rimraf app/client/dist",
|
||||||
"build": "cross-env NODE_ENV=production webpack -p --config webpack.config.prod.js --progress",
|
"build": "cross-env NODE_ENV=production webpack -p --config webpack.config.prod.js --progress",
|
||||||
"lint:check": "eslint ./app/client/src --config .eslintrc && sass-lint ./app/client/src --config .sasslintrc -v -q",
|
"lint:check": "eslint ./app/client/src --config .eslintrc && sass-lint ./app/client/src --config .sasslintrc -v -q",
|
||||||
"lint:fix": "eslint ./app/client/src --config .eslintrc --fix && sass-lint ./app/client/src --config .sasslintrc -v -q --fix",
|
"lint:fix": "eslint ./app/client/src --config .eslintrc --fix && sass-lint ./app/client/src --config .sasslintrc -v -q --fix",
|
||||||
@ -24,6 +24,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@google/markerclusterer": "^1.0.3",
|
"@google/markerclusterer": "^1.0.3",
|
||||||
|
"animate.css": "^3.7.0",
|
||||||
"bootbox": "^4.4.0",
|
"bootbox": "^4.4.0",
|
||||||
"bootstrap": "^4.3.1",
|
"bootstrap": "^4.3.1",
|
||||||
"bootstrap-confirmation2": "^4.1.0",
|
"bootstrap-confirmation2": "^4.1.0",
|
||||||
@ -39,10 +40,11 @@
|
|||||||
"gijgo": "^1.9.13",
|
"gijgo": "^1.9.13",
|
||||||
"jquery": "^3.4.1",
|
"jquery": "^3.4.1",
|
||||||
"jquery-hammerjs": "^2.0.0",
|
"jquery-hammerjs": "^2.0.0",
|
||||||
|
"jquery-hoverintent": "*",
|
||||||
"jquery-zoom": "^1.7.21",
|
"jquery-zoom": "^1.7.21",
|
||||||
"jquery.appear": "^1.0.1",
|
"jquery.appear": "^1.0.1",
|
||||||
"jquery.inputmask": "^3.3.4",
|
"jquery.inputmask": "^3.3.4",
|
||||||
"jquery-hoverintent": "*",
|
"laravel-mix": "^4.1.2",
|
||||||
"mapbox-gl": "^1.2.1",
|
"mapbox-gl": "^1.2.1",
|
||||||
"meta-lightbox": "^1.0.0",
|
"meta-lightbox": "^1.0.0",
|
||||||
"offcanvas-bootstrap": "^2.5.2",
|
"offcanvas-bootstrap": "^2.5.2",
|
||||||
@ -53,9 +55,7 @@
|
|||||||
"routie": "0.0.1",
|
"routie": "0.0.1",
|
||||||
"select2": "^4.0.8",
|
"select2": "^4.0.8",
|
||||||
"smooth-scroll": "^14.2.1",
|
"smooth-scroll": "^14.2.1",
|
||||||
"animate.css": "^3.7.0",
|
"yarn": "^1.17.3"
|
||||||
"yarn": "^1.17.3",
|
|
||||||
"laravel-mix": "^4.1.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "^7.2.5",
|
"autoprefixer": "^7.2.5",
|
||||||
@ -97,12 +97,13 @@
|
|||||||
"sass-lint-fix": "^1.12.1",
|
"sass-lint-fix": "^1.12.1",
|
||||||
"sass-loader": "^6.0.6",
|
"sass-loader": "^6.0.6",
|
||||||
"script-ext-html-webpack-plugin": "^2.1.4",
|
"script-ext-html-webpack-plugin": "^2.1.4",
|
||||||
|
"ss-bootstrap-ui-webpack-boilerplate": "https://github.com/a2nt/webpack-bootstrap-ui-kit",
|
||||||
"style-loader": "^0.19.0",
|
"style-loader": "^0.19.0",
|
||||||
"svg-url-loader": "^2.3.3",
|
"svg-url-loader": "^2.3.3",
|
||||||
|
"terser-webpack-plugin": "^2.1.3",
|
||||||
"uglify-js": "git://github.com/mishoo/UglifyJS2.git#harmony-v2.8.22",
|
"uglify-js": "git://github.com/mishoo/UglifyJS2.git#harmony-v2.8.22",
|
||||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||||
"url-loader": "^0.6.2",
|
"url-loader": "^0.6.2",
|
||||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
|
||||||
"webpack": "^4.39.1",
|
"webpack": "^4.39.1",
|
||||||
"webpack-cli": "^3.3.6",
|
"webpack-cli": "^3.3.6",
|
||||||
"webpack-dev-server": "^3.8.0",
|
"webpack-dev-server": "^3.8.0",
|
||||||
@ -114,7 +115,8 @@
|
|||||||
"block-no-empty": null,
|
"block-no-empty": null,
|
||||||
"color-no-invalid-hex": true,
|
"color-no-invalid-hex": true,
|
||||||
"comment-empty-line-before": [
|
"comment-empty-line-before": [
|
||||||
"always", {
|
"always",
|
||||||
|
{
|
||||||
"ignore": [
|
"ignore": [
|
||||||
"stylelint-commands",
|
"stylelint-commands",
|
||||||
"after-comment"
|
"after-comment"
|
||||||
@ -123,7 +125,8 @@
|
|||||||
],
|
],
|
||||||
"declaration-colon-space-after": "always",
|
"declaration-colon-space-after": "always",
|
||||||
"indentation": [
|
"indentation": [
|
||||||
4, {
|
4,
|
||||||
|
{
|
||||||
"except": [
|
"except": [
|
||||||
"value"
|
"value"
|
||||||
]
|
]
|
||||||
@ -131,7 +134,8 @@
|
|||||||
],
|
],
|
||||||
"max-empty-lines": 2,
|
"max-empty-lines": 2,
|
||||||
"rule-empty-line-before": [
|
"rule-empty-line-before": [
|
||||||
"always", {
|
"always",
|
||||||
|
{
|
||||||
"except": [
|
"except": [
|
||||||
"first-nested"
|
"first-nested"
|
||||||
],
|
],
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
#RewriteEngine On
|
||||||
|
#RewriteCond %{HTTPS} off
|
||||||
|
#RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||||
|
#RewriteCond %{HTTP_HOST} !^www\. [NC]
|
||||||
|
#RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||||
|
|
||||||
### SILVERSTRIPE START ###
|
### SILVERSTRIPE START ###
|
||||||
|
|
||||||
# Deny access to templates (but allow from localhost)
|
# Deny access to templates (but allow from localhost)
|
||||||
|
@ -14,7 +14,8 @@ const autoprefixer = require('autoprefixer');
|
|||||||
|
|
||||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
|
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
|
||||||
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
|
|
||||||
|
const TerserPlugin = require('terser-webpack-plugin');
|
||||||
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||||
|
|
||||||
let plugins = [
|
let plugins = [
|
||||||
@ -106,12 +107,18 @@ module.exports = merge(common, {
|
|||||||
noEmitOnErrors: true, // NoEmitOnErrorsPlugin
|
noEmitOnErrors: true, // NoEmitOnErrorsPlugin
|
||||||
concatenateModules: true, //ModuleConcatenationPlugin
|
concatenateModules: true, //ModuleConcatenationPlugin
|
||||||
minimizer: [
|
minimizer: [
|
||||||
new UglifyJSPlugin({
|
new TerserPlugin({
|
||||||
uglifyOptions: {
|
parallel: true,
|
||||||
sourceMap: false,
|
sourceMap: false,
|
||||||
comments: false
|
terserOptions: {
|
||||||
}
|
parse: {
|
||||||
})
|
ecma: 8,
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
ecma: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user