mirror of
https://github.com/a2nt/silverstripe-webpack.git
synced 2024-10-22 17:05:31 +02:00
Bunch of updates
This commit is contained in:
parent
d638843f92
commit
ff87ba7f16
@ -4,7 +4,8 @@ use SilverStripe\Forms\HTMLEditor\HtmlEditorConfig;
|
|||||||
use SilverStripe\Core\Manifest\ModuleResourceLoader;
|
use SilverStripe\Core\Manifest\ModuleResourceLoader;
|
||||||
use SilverStripe\ORM\Search\FulltextSearchable;
|
use SilverStripe\ORM\Search\FulltextSearchable;
|
||||||
|
|
||||||
HtmlEditorConfig::get('cms')->enablePlugins([
|
$config = HtmlEditorConfig::get('cms');
|
||||||
|
$config->enablePlugins([
|
||||||
'template',
|
'template',
|
||||||
'fullscreen',
|
'fullscreen',
|
||||||
'hr',
|
'hr',
|
||||||
@ -12,11 +13,12 @@ HtmlEditorConfig::get('cms')->enablePlugins([
|
|||||||
'charmap',
|
'charmap',
|
||||||
'visualblocks',
|
'visualblocks',
|
||||||
'lists',
|
'lists',
|
||||||
'anchor',
|
|
||||||
'charcount' => ModuleResourceLoader::resourceURL(
|
'charcount' => ModuleResourceLoader::resourceURL(
|
||||||
'drmartingonzo/ss-tinymce-charcount:client/dist/js/bundle.js'
|
'drmartingonzo/ss-tinymce-charcount:client/dist/js/bundle.js'
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
|
$config->addButtonsToLine(2, 'hr');
|
||||||
|
$config->setOption('block_formats', 'Paragraph=p;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6;Address=address;Pre=pre');
|
||||||
|
$config->setOption('invalid_elements', 'h1');
|
||||||
|
|
||||||
HtmlEditorConfig::get('cms')->insertButtonsAfter('sslink', 'anchor');
|
|
||||||
FulltextSearchable::enable();
|
FulltextSearchable::enable();
|
||||||
|
@ -21,12 +21,12 @@ const AjaxUI = (($) => {
|
|||||||
const $element = $(this._element);
|
const $element = $(this._element);
|
||||||
$element.addClass(`${NAME}-active`);
|
$element.addClass(`${NAME}-active`);
|
||||||
|
|
||||||
$element.bind('click', function (e) {
|
$element.bind('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const $this = $(this);
|
const $this = $(this);
|
||||||
|
|
||||||
$('.ajax').each(function () {
|
$('.ajax').each(function() {
|
||||||
const $this = $(this);
|
const $this = $(this);
|
||||||
$this.removeClass('active');
|
$this.removeClass('active');
|
||||||
$this.parents('.nav-item').removeClass('active');
|
$this.parents('.nav-item').removeClass('active');
|
||||||
@ -77,7 +77,7 @@ const AjaxUI = (($) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
success(data, status, jqXHR) {
|
success(data, status, jqXHR) {
|
||||||
AjaxUI.process(data,jqXHR, callback);
|
AjaxUI.process(data, jqXHR, callback);
|
||||||
|
|
||||||
// google analytics
|
// google analytics
|
||||||
if (typeof G.ga === 'function') {
|
if (typeof G.ga === 'function') {
|
||||||
@ -96,30 +96,30 @@ const AjaxUI = (($) => {
|
|||||||
const js = jqXHR.getResponseHeader('X-Include-JS').split(',') || [];
|
const js = jqXHR.getResponseHeader('X-Include-JS').split(',') || [];
|
||||||
|
|
||||||
// Replace HTML regions
|
// Replace HTML regions
|
||||||
if (typeof (data.regions) === 'object') {
|
if (typeof(data.regions) === 'object') {
|
||||||
for (const key in data.regions) {
|
for (const key in data.regions) {
|
||||||
if (typeof (data.regions[key]) === 'string') {
|
if (typeof(data.regions[key]) === 'string') {
|
||||||
AjaxUI.replaceRegion(data.regions[key], key);
|
AjaxUI.replaceRegion(data.regions[key], key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove already loaded scripts
|
// remove already loaded scripts
|
||||||
$('link[type="text/css"]').each(function () {
|
$('link[type="text/css"]').each(function() {
|
||||||
const i = css.indexOf($(this).attr('href'));
|
const i = css.indexOf($(this).attr('href'));
|
||||||
if (i > -1) {
|
if (i > -1) {
|
||||||
css.splice(i, 1);
|
css.splice(i, 1);
|
||||||
}else if(!$Body.data('unload-blocked')) {
|
} else if (!$Body.data('unload-blocked')) {
|
||||||
console.log(`Unloading: ${ $(this).attr('href')}`);
|
console.log(`Unloading: ${ $(this).attr('href')}`);
|
||||||
$(this).remove();
|
$(this).remove();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('script[type="text/javascript"]').each(function () {
|
$('script[type="text/javascript"]').each(function() {
|
||||||
const i = js.indexOf($(this).attr('src'));
|
const i = js.indexOf($(this).attr('src'));
|
||||||
if (i > -1) {
|
if (i > -1) {
|
||||||
js.splice(i, 1);
|
js.splice(i, 1);
|
||||||
}else if(!$Body.data('unload-blocked')) {
|
} else if (!$Body.data('unload-blocked')) {
|
||||||
console.log(`Unloading: ${ $(this).attr('src')}`);
|
console.log(`Unloading: ${ $(this).attr('src')}`);
|
||||||
$(this).remove();
|
$(this).remove();
|
||||||
}
|
}
|
||||||
@ -142,7 +142,7 @@ const AjaxUI = (($) => {
|
|||||||
console.log('New page is loaded!');
|
console.log('New page is loaded!');
|
||||||
|
|
||||||
// trigger events
|
// trigger events
|
||||||
if (typeof (data.events) === 'object') {
|
if (typeof(data.events) === 'object') {
|
||||||
for (const eventName in data.events) {
|
for (const eventName in data.events) {
|
||||||
$(D).trigger(eventName, [data.events[eventName]]);
|
$(D).trigger(eventName, [data.events[eventName]]);
|
||||||
}
|
}
|
||||||
@ -157,13 +157,13 @@ const AjaxUI = (($) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static preload(items, type = 'text', cache = true) {
|
static preload(items, type = 'text', cache = true, itemCallback = false) {
|
||||||
if (!items.length) {
|
if (!items.length) {
|
||||||
return $.Deferred().resolve().promise();
|
return $.Deferred().resolve().promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
const dfds = [];
|
const dfds = [];
|
||||||
items.forEach((url) => {
|
items.forEach((url, i) => {
|
||||||
const dfd = $.Deferred();
|
const dfd = $.Deferred();
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@ -172,6 +172,9 @@ const AjaxUI = (($) => {
|
|||||||
url,
|
url,
|
||||||
}).always(() => {
|
}).always(() => {
|
||||||
dfd.resolve();
|
dfd.resolve();
|
||||||
|
if (itemCallback) {
|
||||||
|
itemCallback(i, url);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
dfds.push(dfd);
|
dfds.push(dfd);
|
||||||
@ -200,7 +203,7 @@ const AjaxUI = (($) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static _jQueryInterface() {
|
static _jQueryInterface() {
|
||||||
return this.each(function () {
|
return this.each(function() {
|
||||||
// attach functionality to element
|
// attach functionality to element
|
||||||
const $element = $(this);
|
const $element = $(this);
|
||||||
let data = $element.data(DATA_KEY);
|
let data = $element.data(DATA_KEY);
|
||||||
@ -216,7 +219,7 @@ const AjaxUI = (($) => {
|
|||||||
// jQuery interface
|
// jQuery interface
|
||||||
$.fn[NAME] = AjaxUI._jQueryInterface;
|
$.fn[NAME] = AjaxUI._jQueryInterface;
|
||||||
$.fn[NAME].Constructor = AjaxUI;
|
$.fn[NAME].Constructor = AjaxUI;
|
||||||
$.fn[NAME].noConflict = function () {
|
$.fn[NAME].noConflict = function() {
|
||||||
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
$.fn[NAME] = JQUERY_NO_CONFLICT;
|
||||||
return AjaxUI._jQueryInterface;
|
return AjaxUI._jQueryInterface;
|
||||||
};
|
};
|
||||||
@ -230,8 +233,8 @@ const AjaxUI = (($) => {
|
|||||||
$(D).on('layoutRefresh', (e, data) => {
|
$(D).on('layoutRefresh', (e, data) => {
|
||||||
D.title = data.Title;
|
D.title = data.Title;
|
||||||
|
|
||||||
$Html.attr('class','');
|
$Html.attr('class', '');
|
||||||
if(data.ClassName){
|
if (data.ClassName) {
|
||||||
$Html.addClass(data.ClassName);
|
$Html.addClass(data.ClassName);
|
||||||
}
|
}
|
||||||
//data.Link = (data.Link === '/home/') ? '/' : data.Link;
|
//data.Link = (data.Link === '/home/') ? '/' : data.Link;
|
||||||
@ -241,13 +244,13 @@ const AjaxUI = (($) => {
|
|||||||
G.onpopstate = function(event) {
|
G.onpopstate = function(event) {
|
||||||
const $existingLink = $(`a[href^="${ D.location }"]`);
|
const $existingLink = $(`a[href^="${ D.location }"]`);
|
||||||
|
|
||||||
if(event.state !== null && event.state.ajax){
|
if (event.state !== null && event.state.ajax) {
|
||||||
console.log('GOBACK (AJAX state)');
|
console.log('GOBACK (AJAX state)');
|
||||||
AjaxUI.load(event.state.page);
|
AjaxUI.load(event.state.page);
|
||||||
}else if($existingLink.length && $existingLink.hasClass('ajax')){
|
} else if ($existingLink.length && $existingLink.hasClass('ajax')) {
|
||||||
console.log('GOBACK (AJAX link)');
|
console.log('GOBACK (AJAX link)');
|
||||||
$existingLink.trigger('click');
|
$existingLink.trigger('click');
|
||||||
}else{
|
} else {
|
||||||
console.log('GOBACK (HTTP)');
|
console.log('GOBACK (HTTP)');
|
||||||
G.location.href = D.location;
|
G.location.href = D.location;
|
||||||
}
|
}
|
||||||
|
111
app/client/src/js/_components/_ui.form.basics.js
Normal file
111
app/client/src/js/_components/_ui.form.basics.js
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import 'bootstrap-select/js/bootstrap-select';
|
||||||
|
|
||||||
|
import $ from 'jquery';
|
||||||
|
import Events from "../_events";
|
||||||
|
|
||||||
|
const FormBasics = (($) => {
|
||||||
|
// Constants
|
||||||
|
const NAME = 'jsFormBasics';
|
||||||
|
const DATA_KEY = NAME;
|
||||||
|
const $Html = $('html, body');
|
||||||
|
|
||||||
|
class FormBasics {
|
||||||
|
|
||||||
|
constructor(element) {
|
||||||
|
const ui = this;
|
||||||
|
const $element = $(element);
|
||||||
|
|
||||||
|
ui._element = element;
|
||||||
|
$element.data(DATA_KEY, this);
|
||||||
|
|
||||||
|
const $fields = $element.find('input,textarea,select');
|
||||||
|
const $selectFields = $element.find('select:not([readonly])');
|
||||||
|
const $radioOptions = $element.find('input[type="radio"]');
|
||||||
|
|
||||||
|
$selectFields.each((i, el) => {
|
||||||
|
const $el = $(el);
|
||||||
|
|
||||||
|
$el.selectpicker({
|
||||||
|
liveSearch: $el.data('live-search')
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$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').removeClass('checked');
|
||||||
|
if ($el.is(':checked')) {
|
||||||
|
$parent.addClass('checked');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$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(function() {
|
||||||
|
// 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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.jsFormBasics();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return FormBasics;
|
||||||
|
})($);
|
||||||
|
|
||||||
|
export default FormBasics;
|
@ -4,7 +4,7 @@ import $ from 'jquery';
|
|||||||
|
|
||||||
import Events from '../_events';
|
import Events from '../_events';
|
||||||
import Spinner from '../_components/_ui.spinner';
|
import Spinner from '../_components/_ui.spinner';
|
||||||
import FormValidate from './_ui.form.validate';
|
import FormValidateField from "./_ui.form.validate.field";
|
||||||
|
|
||||||
import '../../thirdparty/jquery-te/jquery-te.js';
|
import '../../thirdparty/jquery-te/jquery-te.js';
|
||||||
|
|
||||||
@ -29,25 +29,19 @@ const JqteUI = (($) => {
|
|||||||
constructor(element) {
|
constructor(element) {
|
||||||
const ui = this;
|
const ui = this;
|
||||||
const $element = $(element);
|
const $element = $(element);
|
||||||
const $jqteFields = $element.find('textarea.jqte-field');
|
const validationUI = $element.data('jsFormValidateField');
|
||||||
const validationUI = $element.parents('form').data('jsFormValidate');
|
|
||||||
|
|
||||||
$element.data(DATA_KEY, this);
|
|
||||||
ui._element = element;
|
ui._element = element;
|
||||||
|
$element.data(DATA_KEY, this);
|
||||||
$element.jqte(jqteOptions);
|
$element.jqte(jqteOptions);
|
||||||
|
|
||||||
// dynamic error control
|
// dynamic error control
|
||||||
|
if (validationUI) {
|
||||||
$element.parents('.jqte').find('.jqte_editor').on('change', (e) => {
|
$element.parents('.jqte').find('.jqte_editor').on('change', (e) => {
|
||||||
const $field = $(e.target);
|
validationUI.validate();
|
||||||
const $container = $field.closest('.field');
|
|
||||||
|
|
||||||
if (!$field.text().length && $container.hasClass('required')) {
|
|
||||||
validationUI.setError($container);
|
|
||||||
} else {
|
|
||||||
validationUI.removeError($container);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static dispose() {
|
static dispose() {
|
||||||
console.log(`Destroying: ${NAME}`);
|
console.log(`Destroying: ${NAME}`);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import Events from '../_events';
|
import Events from '../_events';
|
||||||
import LANG from '../lang/_en';
|
import LANG from '../lang/_en';
|
||||||
import FormValidate from './_ui.form.validate';
|
import FormValidateField from "./_ui.form.validate.field";
|
||||||
|
|
||||||
const SteppedForm = (($) => {
|
const SteppedForm = (($) => {
|
||||||
// Constants
|
// Constants
|
||||||
@ -13,6 +13,7 @@ const SteppedForm = (($) => {
|
|||||||
constructor(element) {
|
constructor(element) {
|
||||||
const ui = this;
|
const ui = this;
|
||||||
const $element = $(element);
|
const $element = $(element);
|
||||||
|
|
||||||
$element.data(DATA_KEY, this);
|
$element.data(DATA_KEY, this);
|
||||||
|
|
||||||
if (!$element.find('.steps-counter').length) {
|
if (!$element.find('.steps-counter').length) {
|
||||||
@ -28,16 +29,33 @@ const SteppedForm = (($) => {
|
|||||||
|
|
||||||
ui._steps = $element.find('.step');
|
ui._steps = $element.find('.step');
|
||||||
ui._stepNext = $element.find('.step-next');
|
ui._stepNext = $element.find('.step-next');
|
||||||
|
|
||||||
ui._stepPrev = $element.find('.step-prev');
|
ui._stepPrev = $element.find('.step-prev');
|
||||||
ui._actions = $element.children('.btn-toolbar,.form-actions');
|
ui._actions = $element.children('.btn-toolbar,.form-actions');
|
||||||
|
|
||||||
ui._element = element;
|
ui._element = element;
|
||||||
ui._currentStep = 1;
|
ui._currentStep = 1;
|
||||||
ui._totalSteps = ui._steps.length;
|
ui._totalSteps = ui._steps.last().data('step') || ui._steps.length;
|
||||||
ui._stepsOrder = [];
|
ui._stepsOrder = [];
|
||||||
|
|
||||||
ui._totalStepsCounter.text(ui._totalSteps);
|
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.step('.step[data-step="' + ui._currentStep + '"]');
|
||||||
|
|
||||||
ui._stepNext.on('click', (e) => {
|
ui._stepNext.on('click', (e) => {
|
||||||
@ -78,8 +96,7 @@ const SteppedForm = (($) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui._currentStep++;
|
ui.step('.step[data-step="' + (ui._currentStep + 1) + '"]');
|
||||||
ui.step('.step[data-step="' + ui._currentStep + '"]');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prev() {
|
prev() {
|
||||||
@ -89,17 +106,37 @@ const SteppedForm = (($) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui._currentStep--;
|
ui.step(ui._stepsOrder[ui._currentStep - 1]);
|
||||||
ui.step(ui._stepsOrder[ui._currentStep]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
step(target) {
|
step(target) {
|
||||||
const ui = this;
|
const ui = this;
|
||||||
const $element = $(ui._element);
|
const $element = $(ui._element);
|
||||||
const $target = $element.find(target);
|
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') {
|
if (parseInt($target.data('step')) <= '1') {
|
||||||
ui._stepPrev.hide();
|
ui._stepPrev.hide();
|
||||||
|
$element.trigger(Events.FORM_STEPPED_FIRST_STEP);
|
||||||
} else {
|
} else {
|
||||||
ui._stepPrev.show();
|
ui._stepPrev.show();
|
||||||
}
|
}
|
||||||
@ -107,18 +144,30 @@ const SteppedForm = (($) => {
|
|||||||
if (parseInt($target.data('step')) >= ui._totalSteps) {
|
if (parseInt($target.data('step')) >= ui._totalSteps) {
|
||||||
ui._stepNext.hide();
|
ui._stepNext.hide();
|
||||||
ui._actions.show();
|
ui._actions.show();
|
||||||
|
|
||||||
|
$element.trigger(Events.FORM_STEPPED_LAST_STEP);
|
||||||
} else {
|
} else {
|
||||||
ui._stepNext.show();
|
ui._stepNext.show();
|
||||||
ui._actions.hide();
|
ui._actions.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
ui._currentStep = parseInt($target.data('step'));
|
ui._currentStep = targetStep;
|
||||||
ui._stepsOrder[ui._currentStep] = $target;
|
ui._stepsOrder[ui._currentStep] = $target;
|
||||||
|
|
||||||
ui._steps.removeClass('active');
|
ui._steps.removeClass('active');
|
||||||
$target.addClass('active');
|
$target.addClass('active');
|
||||||
|
|
||||||
ui._currentStepCounter.text(ui._currentStep);
|
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() {
|
static _jQueryInterface() {
|
||||||
|
@ -31,6 +31,10 @@ const FormStorage = (($) => {
|
|||||||
const type = $el.attr('type');
|
const type = $el.attr('type');
|
||||||
const val = STORAGE.getItem(NAME + id);
|
const val = STORAGE.getItem(NAME + id);
|
||||||
|
|
||||||
|
if (type === 'file') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (id && val && type) {
|
if (id && val && type) {
|
||||||
if (type && (type === 'checkbox' || type === 'radio')) {
|
if (type && (type === 'checkbox' || type === 'radio')) {
|
||||||
$el.prop('checked', val);
|
$el.prop('checked', val);
|
||||||
|
120
app/client/src/js/_components/_ui.form.validate.field.js
Normal file
120
app/client/src/js/_components/_ui.form.validate.field.js
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
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', (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;
|
||||||
|
|
||||||
|
// browser checks + required
|
||||||
|
if (!ui._element.checkValidity() ||
|
||||||
|
($el.hasClass('required') && !$el.val().trim().length)
|
||||||
|
) {
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extra checks
|
||||||
|
if (extraChecks) {
|
||||||
|
extraChecks.forEach((check) => {
|
||||||
|
valid = valid && check();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid) {
|
||||||
|
this.removeError();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setError(scrollTo);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setError(scrollTo = true) {
|
||||||
|
const ui = this;
|
||||||
|
const $field = $(ui._element).closest('.field');
|
||||||
|
const pos = $field.offset().top;
|
||||||
|
|
||||||
|
$field.addClass('error');
|
||||||
|
|
||||||
|
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,5 +1,6 @@
|
|||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import Events from "../_events";
|
import Events from "../_events";
|
||||||
|
import FormValidateField from "./_ui.form.validate.field";
|
||||||
|
|
||||||
const FormValidate = (($) => {
|
const FormValidate = (($) => {
|
||||||
// Constants
|
// Constants
|
||||||
@ -19,23 +20,22 @@ const FormValidate = (($) => {
|
|||||||
|
|
||||||
ui._fields = $fields;
|
ui._fields = $fields;
|
||||||
ui._stepped_form = $element.data('jsSteppedForm');
|
ui._stepped_form = $element.data('jsSteppedForm');
|
||||||
|
|
||||||
|
// prevent browsers checks (will do it using JS)
|
||||||
|
$element.attr('novalidate', 'novalidate');
|
||||||
|
|
||||||
$element.on(Events.FORM_INIT_STEPPED, () => {
|
$element.on(Events.FORM_INIT_STEPPED, () => {
|
||||||
ui._stepped_form = $element.data('jsSteppedForm');
|
ui._stepped_form = $element.data('jsSteppedForm');
|
||||||
});
|
});
|
||||||
|
|
||||||
// prevent browsers checks (will do it using JS)
|
// init fields validation
|
||||||
$element.attr('novalidate', 'novalidate');
|
|
||||||
$fields.each((i, el) => {
|
$fields.each((i, el) => {
|
||||||
el.required = false;
|
new FormValidateField(el);
|
||||||
});
|
|
||||||
|
|
||||||
$fields.on('change', (e) => {
|
|
||||||
ui.validateField($(e.target), false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// check form
|
// check form
|
||||||
$element.on('submit', (e) => {
|
$element.on('submit', (e) => {
|
||||||
ui.validateForm($element, true, () => {
|
ui.validate(true, () => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
// switch to step
|
// switch to step
|
||||||
@ -64,52 +64,24 @@ const FormValidate = (($) => {
|
|||||||
this._element = null;
|
this._element = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
validateForm($form, scrollTo = true, badCallback = false) {
|
validate(scrollTo = true, badCallback = false) {
|
||||||
console.log('Checking the form ...');
|
console.log('Checking the form ...');
|
||||||
const ui = this;
|
const ui = this;
|
||||||
|
|
||||||
ui._fields.each(function(i, el) {
|
ui._fields.each(function(i, el) {
|
||||||
const $el = $(el);
|
const $el = $(el);
|
||||||
|
const fieldUI = $el.data('jsFormValidateField');
|
||||||
|
|
||||||
if (!ui.validateField($el)) {
|
if (fieldUI && !fieldUI.validate()) {
|
||||||
if (badCallback) {
|
if (badCallback) {
|
||||||
badCallback();
|
badCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
validateField($el, scrollTo = true) {
|
|
||||||
const $field = $el.closest('.field');
|
|
||||||
|
|
||||||
if (!$el[0].checkValidity() ||
|
|
||||||
($el.hasClass('required') && !$el.val().trim().length)
|
|
||||||
) {
|
|
||||||
this.setError($field, scrollTo);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
this.removeError($field);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
setError($field, scrollTo = true) {
|
|
||||||
const pos = $field.offset().top;
|
|
||||||
|
|
||||||
$field.addClass('error');
|
|
||||||
|
|
||||||
if (scrollTo) {
|
|
||||||
$field.focus();
|
|
||||||
$Html.scrollTop(pos - 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
removeError($field) {
|
|
||||||
$field.removeClass('error');
|
|
||||||
}
|
|
||||||
|
|
||||||
static _jQueryInterface() {
|
static _jQueryInterface() {
|
||||||
return this.each(function() {
|
return this.each(function() {
|
||||||
// attach functionality to element
|
// attach functionality to element
|
||||||
|
@ -5,9 +5,15 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
AJAX: 'ajax-load',
|
AJAX: 'ajax-load',
|
||||||
LOADED: 'load',
|
LOADED: 'load',
|
||||||
|
SET_TARGET_UPDATE: 'set-target-update',
|
||||||
RESTORE_FIELD: 'restore-field',
|
RESTORE_FIELD: 'restore-field',
|
||||||
|
FORM_INIT_BASICS: 'form-basics',
|
||||||
FORM_INIT_STEPPED: 'form-init-stepped',
|
FORM_INIT_STEPPED: 'form-init-stepped',
|
||||||
FORM_INIT_VALIDATE: 'form-init-validate',
|
FORM_INIT_VALIDATE: 'form-init-validate',
|
||||||
|
FORM_INIT_VALIDATE_FIELD: 'form-init-validate-field',
|
||||||
FORM_INIT_STORAGE: 'form-init-storage',
|
FORM_INIT_STORAGE: 'form-init-storage',
|
||||||
FORM_VALIDATION_FAILED: 'form-validation-failed',
|
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',
|
||||||
};
|
};
|
||||||
|
@ -12,10 +12,16 @@ import './_components/routes/index';
|
|||||||
import Events from './_events';
|
import Events from './_events';
|
||||||
import Spinner from './_components/_ui.spinner';
|
import Spinner from './_components/_ui.spinner';
|
||||||
|
|
||||||
import './_components/_ui.shrink';
|
|
||||||
import './_components/_ui.carousel';
|
import './_components/_ui.carousel';
|
||||||
import './_components/_ui.menu';
|
import './_components/_ui.menu';
|
||||||
import './_components/_ui.form.storage';
|
|
||||||
|
import FormBasics from './_components/_ui.form.basics';
|
||||||
|
import FormDatetime from './_components/_ui.form.datetime';
|
||||||
|
import FormStepped from './_components/_ui.form.stepped';
|
||||||
|
import FormValidate from './_components/_ui.form.validate';
|
||||||
|
import FormStorage from './_components/_ui.form.storage';
|
||||||
|
import FormCroppie from './_components/_ui.form.croppie';
|
||||||
|
|
||||||
import AjaxUI from './_components/_ui.ajax';
|
import AjaxUI from './_components/_ui.ajax';
|
||||||
|
|
||||||
import SmoothScroll from 'smooth-scroll';
|
import SmoothScroll from 'smooth-scroll';
|
||||||
@ -144,27 +150,6 @@ const MainUI = (($) => {
|
|||||||
// mark external links
|
// mark external links
|
||||||
$('a.external,a[rel="external"]').attr('target', '_blank');
|
$('a.external,a[rel="external"]').attr('target', '_blank');
|
||||||
|
|
||||||
// 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'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// show encoded emails
|
// show encoded emails
|
||||||
/*$(D).find('.obm').each(function () {
|
/*$(D).find('.obm').each(function () {
|
||||||
if ($(this).attr('data-val') !== undefined) {
|
if ($(this).attr('data-val') !== undefined) {
|
||||||
@ -189,18 +174,23 @@ const MainUI = (($) => {
|
|||||||
//
|
//
|
||||||
|
|
||||||
// scroll links
|
// scroll links
|
||||||
$(D).on('click', '.js-scrollTo', function(e) {
|
$(D).on('click', '.js-scrollTo', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
ScrollTo(this, $(this).attr('data-target'));
|
const el = e.currentTarget;
|
||||||
|
const $el = $(e.currentTarget);
|
||||||
|
|
||||||
|
ScrollTo(el, $el.attr('data-target'));
|
||||||
});
|
});
|
||||||
|
|
||||||
// load external fonts
|
// load external fonts
|
||||||
if ($('[data-extfont]').length) {
|
if ($('[data-extfont]').length) {
|
||||||
$.getScript('//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js', () => {
|
$.getScript('//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js', () => {
|
||||||
const fonts = [];
|
const fonts = [];
|
||||||
$('[data-extfont]').each(function(i) {
|
|
||||||
fonts[i] = $(this).attr('data-extfont');
|
$('[data-extfont]').each(function(i, el) {
|
||||||
|
fonts[i] = $(el).attr('data-extfont');
|
||||||
});
|
});
|
||||||
|
|
||||||
W.WebFont.load({
|
W.WebFont.load({
|
||||||
google: {
|
google: {
|
||||||
families: fonts,
|
families: fonts,
|
||||||
@ -209,6 +199,30 @@ const MainUI = (($) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
// hide spinner
|
||||||
Spinner.hide(() => {
|
Spinner.hide(() => {
|
||||||
$Body.addClass('loaded');
|
$Body.addClass('loaded');
|
||||||
@ -276,14 +290,26 @@ const MainUI = (($) => {
|
|||||||
const $imgLazyUrls = [];
|
const $imgLazyUrls = [];
|
||||||
|
|
||||||
// collect image details
|
// collect image details
|
||||||
$imgs.each(function() {
|
$imgs.each((i, el) => {
|
||||||
const src = $(this).attr('src');
|
const $el = $(el);
|
||||||
const lazySrc = $(this).data('lazy-src');
|
const src = $el.attr('src');
|
||||||
if (src.length) {
|
const lazySrc = $el.data('lazy-src');
|
||||||
|
|
||||||
|
if (src && src.length) {
|
||||||
$imgUrls.push(src);
|
$imgUrls.push(src);
|
||||||
}
|
}
|
||||||
if (lazySrc) {
|
if (lazySrc && lazySrc.length) {
|
||||||
$imgLazyUrls.push(lazySrc);
|
$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');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -293,14 +319,6 @@ const MainUI = (($) => {
|
|||||||
|
|
||||||
// load lazy images
|
// load lazy images
|
||||||
AjaxUI.preload($imgLazyUrls).then(() => {
|
AjaxUI.preload($imgLazyUrls).then(() => {
|
||||||
// update lazy img src
|
|
||||||
$('img[data-lazy-src]').each(function() {
|
|
||||||
if (!$(this).attr('src')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$(this).attr('src', $(this).data('lazy-src'));
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('All images are loaded!');
|
console.log('All images are loaded!');
|
||||||
|
|
||||||
$(W).trigger('images-lazy-loaded');
|
$(W).trigger('images-lazy-loaded');
|
||||||
|
@ -8,10 +8,11 @@ img {
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:hover,
|
a,
|
||||||
a:focus,
|
button,
|
||||||
button:hover,
|
.jqte_tool_icon {
|
||||||
button:focus {
|
&:hover,
|
||||||
|
&:focus {
|
||||||
opacity: .8;
|
opacity: .8;
|
||||||
|
|
||||||
.fas,
|
.fas,
|
||||||
@ -22,11 +23,20 @@ button:focus {
|
|||||||
&.far {
|
&.far {
|
||||||
transform: scale(-1, 1);
|
transform: scale(-1, 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.jqte_tool_icon {
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
transform: scale(-1, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// transactions
|
// transactions
|
||||||
.transition,
|
.transition,
|
||||||
a, a img,
|
a, a img,
|
||||||
|
.jqte_tool_icon,
|
||||||
a .fas, a .fab, a .far,
|
a .fas, a .fab, a .far,
|
||||||
a.fas, a.fab, a.far,
|
a.fas, a.fab, a.far,
|
||||||
button .fas, button .fab, button .far,
|
button .fas, button .fab, button .far,
|
||||||
@ -43,16 +53,73 @@ button, input, optgroup, select, textarea,
|
|||||||
transition: all 0.4s ease;
|
transition: all 0.4s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alert-fixed-top {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
z-index: 999;
|
||||||
|
left: 4rem;
|
||||||
|
right: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-toolbar {
|
.btn-toolbar {
|
||||||
margin-top: $grid-gutter-height / 2;
|
margin-top: $grid-gutter-height / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.field {
|
.field {
|
||||||
|
position: relative;
|
||||||
|
margin: 2rem 0;
|
||||||
margin: ($grid-gutter-height / 4) 0;
|
margin: ($grid-gutter-height / 4) 0;
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
margin-top: 0;
|
margin-top: 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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.required,
|
||||||
|
.message.error {
|
||||||
|
@extend .alert;
|
||||||
|
|
||||||
|
@extend .alert-danger;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stick navbar to top using mobile layout
|
// stick navbar to top using mobile layout
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
@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";
|
||||||
|
|
||||||
|
@ -1 +1,48 @@
|
|||||||
@import "../_variables";
|
@import "../_variables";
|
||||||
|
|
||||||
|
@import "~bootstrap/scss/tables";
|
||||||
|
|
||||||
|
.image {
|
||||||
|
&.left {
|
||||||
|
float: left;
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.center {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right {
|
||||||
|
float: right;
|
||||||
|
clear: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
|
||||||
|
@extend .table-striped;
|
||||||
|
}
|
||||||
|
@ -8,12 +8,12 @@
|
|||||||
|
|
||||||
namespace Site\Extensions;
|
namespace Site\Extensions;
|
||||||
|
|
||||||
|
|
||||||
use Sheadawson\Linkable\Forms\LinkField;
|
use Sheadawson\Linkable\Forms\LinkField;
|
||||||
use Sheadawson\Linkable\Models\Link;
|
use Sheadawson\Linkable\Models\Link;
|
||||||
use SilverStripe\Forms\FieldList;
|
use SilverStripe\Forms\FieldList;
|
||||||
use SilverStripe\Forms\TextField;
|
use SilverStripe\Forms\TextField;
|
||||||
use SilverStripe\ORM\DataExtension;
|
use SilverStripe\ORM\DataExtension;
|
||||||
|
use SilverStripe\Security\Member;
|
||||||
|
|
||||||
class SocialExtension extends DataExtension
|
class SocialExtension extends DataExtension
|
||||||
{
|
{
|
||||||
@ -59,4 +59,18 @@ class SocialExtension extends DataExtension
|
|||||||
|
|
||||||
$fields->addFieldsToTab('Root.Social', $linkFields);
|
$fields->addFieldsToTab('Root.Social', $linkFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function byPhone($phone)
|
||||||
|
{
|
||||||
|
$links = Link::get()->filter('Phone', $phone);
|
||||||
|
|
||||||
|
if ($links->exists()) {
|
||||||
|
return Member::get()->filter(
|
||||||
|
'PhoneNumberID',
|
||||||
|
array_keys($links->map('ID', 'Title')->toArray())
|
||||||
|
)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,10 @@ class PageController extends ContentController
|
|||||||
public function getSiteWideMessage()
|
public function getSiteWideMessage()
|
||||||
{
|
{
|
||||||
$session = $this->getRequest()->getSession();
|
$session = $this->getRequest()->getSession();
|
||||||
|
$message = $session->get('SiteWideMessage');
|
||||||
$session->clear('SiteWideMessage');
|
$session->clear('SiteWideMessage');
|
||||||
|
|
||||||
return $session->get('SiteWideMessage');
|
return $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function CurrentTime()
|
public function CurrentTime()
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
<% if $SiteWideMessage %>
|
<% if $SiteWideMessage %>
|
||||||
|
<% with $SiteWideMessage %>
|
||||||
<div class="alert alert-fixed-top alert-{$Type}">
|
<div class="alert alert-fixed-top alert-{$Type}">
|
||||||
{$Message}
|
{$Message}
|
||||||
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
|
<i class="fas fa-times"></i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<% end_with %>
|
||||||
<% end_if %>
|
<% end_if %>
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
"dnadesign/silverstripe-elemental-virtual": "*",
|
"dnadesign/silverstripe-elemental-virtual": "*",
|
||||||
"dnadesign/silverstripe-elemental-userforms": "*",
|
"dnadesign/silverstripe-elemental-userforms": "*",
|
||||||
"dynamic/silverstripe-elemental-blocks": "*",
|
"dynamic/silverstripe-elemental-blocks": "*",
|
||||||
"hestec/silverstripe-cookiebar": "^1.0",
|
|
||||||
"drmartingonzo/ss-tinymce-charcount": "^1.0",
|
"drmartingonzo/ss-tinymce-charcount": "^1.0",
|
||||||
"axllent/silverstripe-version-truncator": "*",
|
"axllent/silverstripe-version-truncator": "*",
|
||||||
"firesphere/googlemapsfield": "^1.0@dev",
|
"firesphere/googlemapsfield": "^1.0@dev",
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
"bootstrap": "^4.1.1",
|
"bootstrap": "^4.1.1",
|
||||||
"bootstrap-datepicker": "^1.8.0",
|
"bootstrap-datepicker": "^1.8.0",
|
||||||
"bootstrap-offcanvas": "^1.0.0",
|
"bootstrap-offcanvas": "^1.0.0",
|
||||||
|
"bootstrap-select": "^1.13.2",
|
||||||
"bootstrap-timepicker": "^0.5.2",
|
"bootstrap-timepicker": "^0.5.2",
|
||||||
"core-util-is": "^1.0.2",
|
"core-util-is": "^1.0.2",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
@ -35,6 +36,7 @@
|
|||||||
"jquery": "^3.3.1",
|
"jquery": "^3.3.1",
|
||||||
"jquery-hammerjs": "^2.0.0",
|
"jquery-hammerjs": "^2.0.0",
|
||||||
"jquery-zoom": "^1.7.21",
|
"jquery-zoom": "^1.7.21",
|
||||||
|
"jquery.appear": "^1.0.1",
|
||||||
"mapbox-gl": "^0.48.0",
|
"mapbox-gl": "^0.48.0",
|
||||||
"meta-lightbox": "^1.0.0",
|
"meta-lightbox": "^1.0.0",
|
||||||
"offcanvas-bootstrap": "^2.5.2",
|
"offcanvas-bootstrap": "^2.5.2",
|
||||||
|
Loading…
Reference in New Issue
Block a user