diff --git a/dist/index.html b/dist/index.html index ee8097e..91a5505 100644 --- a/dist/index.html +++ b/dist/index.html @@ -1 +1,7 @@ -Webpack Bootstrap 4 UI Demo

Content Header

Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Header #2

Test ImageContent Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Header #3

Test Image Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Header #2

Header #3

Header #4

Header #5
Header #6

Test Image Content Text Link ... Content Text Bold ... Content Text Italic ... Content Text Bold-Italic ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ...

  • First
  • Second
  • Third

Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

  1. First
    • First
    • Second
      1. First
      2. Second
      3. Third
      • First
      • Second
      • Third
    • Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

  2. {paragraph} Second

    {paragraph} Second #2

  3. Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Table #1: Default

#1#2#3
#1-1#1-2#1-3
#2-1#2-2#2-3
#3-1#3-2#3-3

Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Table #2: Border-less

#1#2#3
#1-1#1-2#1-3
#2-1#2-2#2-3
#3-1#3-2#3-3

Content Header

Some content ...
Some kind image
Some kind image
Some kind image
Some kind image

Content Header

Some content ...

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

\ No newline at end of file +Webpack Bootstrap 4 UI Demo

Content Header

+ + + + +
+

Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Header #2

Test ImageContent Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Header #3

Test Image Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Header #2

Header #3

Header #4

Header #5
Header #6

Test Image Content Text Link ... Content Text Bold ... Content Text Italic ... Content Text Bold-Italic ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ... Content Text Bla-bla-bla ...

  • First
  • Second
  • Third

Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

  1. First
    • First
    • Second
      1. First
      2. Second
      3. Third
      • First
      • Second
      • Third
    • Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

  2. {paragraph} Second

    {paragraph} Second #2

  3. Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Table #1: Default

#1#2#3
#1-1#1-2#1-3
#2-1#2-2#2-3
#3-1#3-2#3-3

Content Text Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Table #2: Border-less

#1#2#3
#1-1#1-2#1-3
#2-1#2-2#2-3
#3-1#3-2#3-3

Content Header

Some content ...
Some kind image
Some kind image
Some kind image
Some kind image

Content Header

Some content ...

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

\ No newline at end of file diff --git a/package.json b/package.json index 1daf5fb..545112d 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "bootstrap-confirmation2": "^4.1.0", "bootstrap-datepicker": "^1.9.0", "bootstrap-offcanvas": "^1.0.0", - "bootstrap-select": "^1.13.10", + "bootstrap-select": "github:snapappointments/bootstrap-select#v2.0.0-beta1", "bootstrap-table": "^1.14.2", "bootstrap-timepicker": "^0.5.2", "core-util-is": "^1.0.2", @@ -110,8 +110,7 @@ "block-no-empty": null, "color-no-invalid-hex": true, "comment-empty-line-before": [ - "always", - { + "always", { "ignore": [ "stylelint-commands", "after-comment" @@ -120,8 +119,7 @@ ], "declaration-colon-space-after": "always", "indentation": [ - 4, - { + 4, { "except": [ "value" ] @@ -129,8 +127,7 @@ ], "max-empty-lines": 2, "rule-empty-line-before": [ - "always", - { + "always", { "except": [ "first-nested" ], diff --git a/src/js/_components/_ui.carousel.js b/src/js/_components/_ui.carousel.js index 1795ed7..4f0b84f 100755 --- a/src/js/_components/_ui.carousel.js +++ b/src/js/_components/_ui.carousel.js @@ -1,5 +1,8 @@ import $ from 'jquery'; +import 'hammerjs/hammer'; +import 'jquery-hammerjs/jquery.hammer'; + import Events from '../_events'; const CarouselUI = (($) => { @@ -87,4 +90,4 @@ const CarouselUI = (($) => { return CarouselUI; })($); -export default CarouselUI; \ No newline at end of file +export default CarouselUI; diff --git a/src/js/_components/_ui.form.basics.js b/src/js/_components/_ui.form.basics.js index 7e9b7ed..6e702de 100755 --- a/src/js/_components/_ui.form.basics.js +++ b/src/js/_components/_ui.form.basics.js @@ -1,6 +1,8 @@ import $ from 'jquery'; -import 'bootstrap-select/js/bootstrap-select'; +import 'bootstrap-select/dist/js/bootstrap-select'; +$.fn.selectpicker.Constructor.BootstrapVersion = '4'; + import 'jquery.inputmask/dist/jquery.inputmask.bundle'; import Events from "../_events"; @@ -12,6 +14,8 @@ const FormBasics = (($) => { const NAME = 'jsFormBasics'; const DATA_KEY = NAME; const $Html = $('html, body'); + const W = window; + const D = document; class FormBasics { @@ -27,6 +31,7 @@ const FormBasics = (($) => { const $fields = $element.find(Events.FORM_FIELDS); // init fields ui $fields.each((i, el) => { + // skip some fields here new FormFieldUI(el); }); @@ -51,12 +56,12 @@ const FormBasics = (($) => { // wrap options if (maxOptions > 1) { - $el.on('rendered.bs.select,changed.bs.select,refreshed.bs.select,loaded.bs.select', () => { + const wrapOptions = () => { if (!$el.val().length) { return true; } - const $container = $el.parent().find('.filter-option-inner-inner'); + const $container = $el.parent().find('.dropdown-toggle .filter-option'); const val = $container.text(); const vals = val.split(separator); let html = ''; @@ -67,7 +72,7 @@ const FormBasics = (($) => { }); html += `${ opt - } `; + } `; }); @@ -87,26 +92,25 @@ const FormBasics = (($) => { 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: hidden picker - $el.selectpicker('render'); - $el.selectpicker('refresh'); - $el.selectpicker('toggle'); - document.activeElement.blur(); - window.scroll(0, 0); - - //$el.selectpicker('show'); - //$el.selectpicker('hide'); - - /*$el.parents('.field.dropdown').find('.dropdown-toggle').click(); - $el.parents('.field.dropdown').find('.dropdown-toggle').click(); - $el.parents('.field.dropdown').find('.dropdown-toggle').blur();*/ }); + // 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); @@ -128,7 +132,14 @@ const FormBasics = (($) => { const $el = $(e.currentTarget); const $parent = $el.parents('.radio'); - $parent.siblings('.radio').removeClass('checked'); + $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'); } @@ -152,7 +163,7 @@ const FormBasics = (($) => { } static _jQueryInterface() { - return this.each(function() { + return this.each(() => { // attach functionality to element const $element = $(this); let data = $element.data(DATA_KEY); @@ -173,18 +184,13 @@ const FormBasics = (($) => { return FormBasics._jQueryInterface; }; + const init = () => { + $('form').jsFormBasics(); + }; + // 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(); - }); + $(W).on(`${Events.AJAX} ${Events.LOADED}`, () => { + init(); }); return FormBasics; diff --git a/src/js/_components/_ui.form.croppie.js b/src/js/_components/_ui.form.croppie.js index dab29a8..fce5038 100755 --- a/src/js/_components/_ui.form.croppie.js +++ b/src/js/_components/_ui.form.croppie.js @@ -45,7 +45,7 @@ const CroppieUI = (($) => { $el.append( '
' + - ' Remove
' + '' ); //$el.append(ui.inputData); @@ -68,7 +68,8 @@ const CroppieUI = (($) => { this.readFile(e.currentTarget); }); - $el.find('.btn-remove').on('click', (e) => { + ui.$btnRemove = $el.find('.btn-remove'); + ui.$btnRemove.on('click', (e) => { e.preventDefault(); ui.uploadCrop.removeClass('ready'); @@ -79,6 +80,10 @@ const CroppieUI = (($) => { ui.uploadCropWrap.hide(); }); + + if (ui.$el.find('img.croppie-image').length) { + ui.$btnRemove.show(); + } } readFile(input) { @@ -97,6 +102,7 @@ const CroppieUI = (($) => { ui.uploadCrop.show(); ui.uploadCropWrap.show(); + ui.$btnRemove.show(); } reader.readAsDataURL(input.files[0]); diff --git a/src/js/_components/_ui.form.datetime.js b/src/js/_components/_ui.form.datetime.js index d2fd59a..1456f8d 100755 --- a/src/js/_components/_ui.form.datetime.js +++ b/src/js/_components/_ui.form.datetime.js @@ -46,7 +46,7 @@ const DatetimeUI = (($) => { if ($el.hasClass('time') || $el.attr('type') === 'time') { $el.attr('readonly', 'true'); $el.timepicker($.extend({ - defaultTime: $el.data('default-time'), + snapToStep: true, icons: { up: 'fas fa-chevron-up', down: 'fas fa-chevron-down', @@ -54,7 +54,11 @@ const DatetimeUI = (($) => { }, $el.data())).on('show.timepicker', (e) => { const $el = $(e.currentTarget); const $dropdown = $Body.find('.bootstrap-timepicker-widget'); - $dropdown.find('tbody').append('Clear'); + + if (!$dropdown.find('[data-action="clear"]').length) { + $dropdown.find('tbody').append('Clear'); + } + const $clearBtn = $dropdown.find('[data-action="clear"]'); $clearBtn.on('click', (e) => { e.preventDefault(); diff --git a/src/js/_components/_ui.form.fields.js b/src/js/_components/_ui.form.fields.js index fd294c3..06c3593 100755 --- a/src/js/_components/_ui.form.fields.js +++ b/src/js/_components/_ui.form.fields.js @@ -13,7 +13,7 @@ const FormFieldUI = (($) => { const ui = this; ui.$el = $(el); - ui.$el.data(DATA_KEY, this); + ui.$el.data(DATA_KEY, ui); ui.shown = true; //ui.$actions = ui.$el.parents('form').children('.btn-toolbar,.form-actions'); @@ -22,7 +22,24 @@ const FormFieldUI = (($) => { 'checked': ui.$el.is(':checked'), }; + // bootstrap collapse integration + ui.$el.parents('.optionset').not('.field').removeClass('collapse'); + ui.$collapse = ui.$el.parents('.field.collapse').not('.composite').first(); + if (ui.$collapse.length) { + ui.$el.removeClass('collapse'); + + ui.$collapse.on('show.bs.collapse', (e) => { + ui.show(); + }); + + ui.$collapse.on('hidden.bs.collapse', (e) => { + ui.hide(); + }); + } + ui.$el.addClass(`${NAME}-active`); + + return ui; } // Public methods @@ -32,7 +49,6 @@ const FormFieldUI = (($) => { $el.removeClass(`${NAME}-active`); $.removeData(this._el, DATA_KEY); - this._el = null; } show() { @@ -42,11 +58,15 @@ const FormFieldUI = (($) => { ui.restore(); ui.shown = true; - if ($el.hasClass('collapse')) { - $el.collapse('show'); + /*if (ui.$collapse.length) { + ui.$collapse.collapse('show'); } - $el.trigger('change'); + if ($el.hasClass('collapse')) { + $el.collapse('show'); + }*/ + + $el.trigger('shown.' + NAME); } hide() { @@ -56,21 +76,22 @@ const FormFieldUI = (($) => { ui.wipe(); ui.shown = false; + /*if (ui.$collapse.length) { + ui.$collapse.collapse('hide'); + } + if ($el.hasClass('collapse')) { $el.collapse('hide'); } - $el.trigger('change'); + $el.trigger('change');*/ + $el.trigger('hidden.' + NAME); } wipe() { const ui = this; const $el = ui.$el; - if (!ui.shown) { - return; - } - ui.vals = { 'name': $el.attr('name'), 'val': $el.val(), @@ -84,9 +105,10 @@ const FormFieldUI = (($) => { restore() { const ui = this; const $el = ui.$el; + const checked = ui.vals['checked']; $el.val(ui.vals['val']); - $el.prop('checked', ui.vals['checked']); + $el.prop('checked', checked); } static _jQueryInterface() { diff --git a/src/js/_components/_ui.form.storage.js b/src/js/_components/_ui.form.storage.js index 9878408..dab9dea 100755 --- a/src/js/_components/_ui.form.storage.js +++ b/src/js/_components/_ui.form.storage.js @@ -83,7 +83,7 @@ const FormStorage = (($) => { $element.data(DATA_KEY).clear(); }); - $element.find('button,[type="submit"],[type="clear"]').on('click', () => { + $element.find('.btn-toolbar,.form-actions').children('button,[type="submit"],[type="clear"]').on('click', () => { $element.data(DATA_KEY).clear(); }); diff --git a/src/js/_components/_ui.form.validate.field.js b/src/js/_components/_ui.form.validate.field.js index a3a239d..277dda2 100755 --- a/src/js/_components/_ui.form.validate.field.js +++ b/src/js/_components/_ui.form.validate.field.js @@ -20,7 +20,7 @@ const FormValidateField = (($) => { // prevent browsers checks (will do it using JS) $element.attr('novalidate', 'novalidate'); - $element.on('change', (e) => { + $element.on('change focusout', (e) => { ui.validate(false); }); @@ -45,19 +45,25 @@ const FormValidateField = (($) => { let valid = true; let msg = null; + const val = $el.val(); + // browser checks + required if (!ui._element.checkValidity() || - ($el.hasClass('required') && !$el.val().trim().length) + ($el.hasClass('required') && (!val.length || !val.trim().length || + ui.isHtml(val) && !$(val).text().length + )) ) { valid = false; } // validate URL - if ($el.hasClass('url') && $el.val().trim().length && !this.valideURL($el.val())) { + 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) => { @@ -65,25 +71,27 @@ const FormValidateField = (($) => { }); } - this.removeError(); if (valid) { return true; } - setTimeout(() => { - this.setError(scrollTo, msg); - }, 500); + 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 + '((([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); } diff --git a/src/js/_components/_ui.form.validate.js b/src/js/_components/_ui.form.validate.js index ea3cd22..6e11bf0 100755 --- a/src/js/_components/_ui.form.validate.js +++ b/src/js/_components/_ui.form.validate.js @@ -31,6 +31,11 @@ const FormValidate = (($) => { // init fields validation $fields.each((i, el) => { + // skip some fields here + if ($(el).attr('role') === 'combobox') { + return; + } + new FormValidateField(el); }); diff --git a/src/js/_components/_ui.video.preview.js b/src/js/_components/_ui.video.preview.js index 83d5a50..9c2088c 100755 --- a/src/js/_components/_ui.video.preview.js +++ b/src/js/_components/_ui.video.preview.js @@ -25,16 +25,19 @@ const VideoPreviewUI = (($) => { 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_id = video[4]; - } - if (video[1] === 'youtu') { - video_id = video[3]; + if (video[1] === 'youtube' || video[1] === 'youtube-nocookie' || video[1] === 'youtu') { + video_id = YouTubeGetID(href); } if (video[1] == 'vimeo') { diff --git a/src/js/_main.js b/src/js/_main.js index cb66d6e..5a479be 100755 --- a/src/js/_main.js +++ b/src/js/_main.js @@ -5,6 +5,9 @@ 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'; @@ -12,17 +15,21 @@ import './_components/routes/index'; import Events from './_events'; import Spinner from './_components/_ui.spinner'; +import './_components/_ui.video.preview'; import './_components/_ui.carousel'; import './_components/_ui.menu'; + import FormBasics from './_components/_ui.form.basics'; -import FormDatetime from './_components/_ui.form.datetime'; +//import FormToggleUI from './_components/_ui.form.fields.toggle'; +//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 NoCaptcha from './_components/_ui.nocaptcha'; import SmoothScroll from 'smooth-scroll'; const smoothScroll = SmoothScroll(); @@ -145,7 +152,9 @@ const MainUI = (($) => { $('a.offline').addClass('offline-available'); } - this.loadImages(); + if (typeof AjaxUI !== 'undefined') { + this.loadImages(); + } // mark external links $('a.external,a[rel="external"]').attr('target', '_blank'); diff --git a/src/js/app.js b/src/js/app.js index 7b60fb9..1ec0731 100755 --- a/src/js/app.js +++ b/src/js/app.js @@ -7,7 +7,10 @@ import 'bootstrap/js/dist/alert'; import 'bootstrap/js/dist/button'; import 'bootstrap/js/dist/carousel'; import 'bootstrap/js/dist/collapse'; -import 'bootstrap/js/dist/dropdown'; + +// conflicting with bootstrap-select/dist/js/bootstrap-select +//import 'bootstrap/js/dist/dropdown'; + import 'bootstrap/js/dist/modal'; import 'bootstrap/js/dist/tooltip'; import 'bootstrap/js/dist/popover'; diff --git a/src/scss/_components/_ui.carousel.scss b/src/scss/_components/_ui.carousel.scss index 4bec96c..babd8dd 100755 --- a/src/scss/_components/_ui.carousel.scss +++ b/src/scss/_components/_ui.carousel.scss @@ -2,6 +2,14 @@ * Bootstrap carousel improvement */ +.carousel-item { + &.active { + display: flex !important; + justify-content: center; + align-items: flex-start; + } +} + .carousel-control-prev, .carousel-control-next { z-index: 2; diff --git a/src/scss/_variables.scss b/src/scss/_variables.scss index 530675d..173dc6e 100755 --- a/src/scss/_variables.scss +++ b/src/scss/_variables.scss @@ -2,6 +2,9 @@ * Your custom variables */ +$grid-breakpoints: (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1390px, xxxl: 1590px); +$container-max-widths: (sm: 540px, md: 720px, lg: 960px, xl: 1140px, xxl: 1330px, xxxl: 1560px); + $font-family-base: "Lato", sans-serif; $grid-gutter-height: 8rem;