From 68fc9e55e538e03f94509731ab41a0c8cf96710f Mon Sep 17 00:00:00 2001 From: George Halkiadakis Date: Mon, 17 Apr 2023 12:12:22 +0300 Subject: setup a real server environment (apache DocumentRoot=/var/www/public) --- public/assets/js/forms/ajaxForm.js | 188 +++++++++++++++++++++++++++++ public/assets/js/forms/clearinput.js | 16 +++ public/assets/js/forms/customValidators.js | 11 ++ public/assets/js/forms/password.js | 15 +++ public/assets/js/forms/select.js | 52 ++++++++ public/assets/js/forms/serialize.js | 30 +++++ public/assets/js/forms/textarea.js | 26 ++++ public/assets/js/forms/validateform.js | 3 + 8 files changed, 341 insertions(+) create mode 100644 public/assets/js/forms/ajaxForm.js create mode 100644 public/assets/js/forms/clearinput.js create mode 100644 public/assets/js/forms/customValidators.js create mode 100644 public/assets/js/forms/password.js create mode 100644 public/assets/js/forms/select.js create mode 100644 public/assets/js/forms/serialize.js create mode 100644 public/assets/js/forms/textarea.js create mode 100644 public/assets/js/forms/validateform.js (limited to 'public/assets/js/forms') diff --git a/public/assets/js/forms/ajaxForm.js b/public/assets/js/forms/ajaxForm.js new file mode 100644 index 0000000..6ade446 --- /dev/null +++ b/public/assets/js/forms/ajaxForm.js @@ -0,0 +1,188 @@ +$.defineAttributePlugin('ajaxform', ['serialize', 'debounce'], function ($element, options, serialize, debounce) { + options = options || {}; + options.Url = options.Url || $element.attr('action'); + + var loader = ''; + var submit; + var onError = debounce(scrollToFirstError, 100); + + onError(); + + function getElementToReplace() { + var $toReplace; + if (options.ElementID) { + $toReplace = $("#" + options.ElementID); + } + else { + $toReplace = $element.closest('.ajax-replace-container'); + if ($toReplace.length === 0) { + $toReplace = $element.closest('div.form'); + } + if ($toReplace.length === 0) { + $toReplace = $element; + } + } + return $toReplace; + } + + function ajaxComplete(response, $element) { + var flow = response.getResponseHeader("X-FlowComplete"); + + if (flow) { + + $element.trigger('flowcomplete', flow); + } + } + + function createReplacement(content) { + return $(content); // $('
' + content + '
'); //.find('> *'); + } + var submitting = false; + submit = function () { + if (!options.Url || submitting) { + return; + } + submitting = true; + mask(); + var headers = { + "X-NoRedirect": "true" + }; + var $toReplace = getElementToReplace(); + if ($toReplace.is('.ajax-modal')) { + headers["X-Modal"] = "true"; + } + var result = { + redirected: false + }; + + var ajaxOptions = { + url: options.Url, + headers: headers, + beforeSend: function () { + $('body').trigger('TopLoader:Show'); + $element.find('[type="submit"]').attr('disabled', 'disabled'); + }, + type: 'post', + success: function (content, status, response) { + if (content.RedirectUrl) { + result.redirected = true; + window.location.href = content.RedirectUrl; + return; + } + if (content) { + var $replacement = createReplacement(content); + $toReplace.replaceWith($replacement); + $replacement.parseAttributePlugins(); + ajaxComplete(response, $replacement); + $replacement.trigger('ajaxForm.submitted'); + } + else { + ajaxComplete(response, $element); + } + + + }, + complete: function () { + $('body').trigger('TopLoader:Hide'); + if (!result.redirected) { + unmask(); + $element.find('[clicked]').removeAttr('clicked'); + $element.find('[type="submit"]').removeAttr('disabled'); + submitting = false; + } + }, + error: function (r) { + if (r.status === 401) { + location.reload(); + return; + } + } + }; + + if ($element.is("form") && $element.prop("enctype") === "multipart/form-data") { + ajaxOptions.data = new FormData($element.get(0)); + ajaxOptions.contentType = false; + ajaxOptions.processData = false; + } else { + var $elements = $element.find('input[name], textarea[name], select[name], :submit[name][clicked=true]') + ajaxOptions.data = serialize($elements); + } + + $.ajax(ajaxOptions); + }; + + function mask() { + $element.find('[clicked]').addClass('in-progress').append(loader); + $element.trigger('ajaxform.submitting'); + } + function unmask() { + $element.find('[clicked]').removeClass('in-progress').find('.ajax-loader').remove(); + $element.trigger('ajaxform.complete'); + } + + if (options.LazyVerification) { + var s = submit; + submit = function () { + $.ajax({ + url: options.LazyVerification, + beforeSend: function () { + $element.find('[type="submit"]').attr('disabled', 'disabled'); + }, + type: 'post', + success: function (content, status, response) { + $element.append(content); + s(); + }, + complete: function () { + $element.find('[type="submit"]').removeAttr('disabled'); + } + }); + }; + } + $element.find("[type=submit]").click(function () { + $element.find("[type=submit]").removeAttr("clicked"); + $(this).attr("clicked", "true"); + }); + if ($element.is('form')) { + $element.on('submit', function (e) { + + if (options.Url) { + e.preventDefault(); + } + var clickedButton = $element.find('[clicked]'); + if (!clickedButton.is('.cancel')) { + if (!$element.valid()) { + console.warn('validation error'); + onError(); + return; + } + } + submit(); + }); + } + else { + $element.find('[type="submit"]').click(function (e) { + e.preventDefault(); + e.stopPropagation(); + submit(); + }); + } + $element.data('ajaxform.submit', submit); + + function scrollToFirstError() { + var $erroneousElement = $element.find(".field-validation-error").eq(0).parents(".field"); + + if ($erroneousElement.length === 1) { + var top = $erroneousElement.offset().top; + var $header = $('.headerWrp'); + if ($header.length) { + top -= $header.height() + 80; + } + $('html,body').animate({ + scrollTop: top + }, 500); + $erroneousElement.find("input").focus(); + } + } + +}); diff --git a/public/assets/js/forms/clearinput.js b/public/assets/js/forms/clearinput.js new file mode 100644 index 0000000..903244f --- /dev/null +++ b/public/assets/js/forms/clearinput.js @@ -0,0 +1,16 @@ +$$plugins.define('clearinput', function (element, options) { + var input = element.previousElementSibling; + + input.addEventListener("keyup", function (e) { + e.preventDefault(); + if (input.value !== "") { + element.classList.add("active"); + } + }); + + element.addEventListener("click", function (e) { + e.preventDefault(); + input.value = ""; + element.classList.remove("active"); + }); +}); diff --git a/public/assets/js/forms/customValidators.js b/public/assets/js/forms/customValidators.js new file mode 100644 index 0000000..3ebecf9 --- /dev/null +++ b/public/assets/js/forms/customValidators.js @@ -0,0 +1,11 @@ +define(['jQuery', 'jquery.validate', 'jquery.validate.unobtrusive'], function () { + $.validator.unobtrusive.adapters.add("requirechecked", [], + function (options) { + options.rules['requirechecked'] = 'requirechecked'; + options.messages['requirechecked'] = options.message; + } + ); + $.validator.addMethod("requirechecked", function (value, element, e) { + return $(element).is(':checked'); + }); +}); \ No newline at end of file diff --git a/public/assets/js/forms/password.js b/public/assets/js/forms/password.js new file mode 100644 index 0000000..c0ccbef --- /dev/null +++ b/public/assets/js/forms/password.js @@ -0,0 +1,15 @@ +$$plugins.define('password', function (element, options) { + var input = element.previousElementSibling; + + element.addEventListener("click", function (e) { + e.preventDefault(); + if (input.type === 'password') { + input.type = 'text'; + element.classList.add('disabled'); + } + else { + input.type = 'password'; + element.classList.remove('disabled'); + } + }); +}); diff --git a/public/assets/js/forms/select.js b/public/assets/js/forms/select.js new file mode 100644 index 0000000..3ea5435 --- /dev/null +++ b/public/assets/js/forms/select.js @@ -0,0 +1,52 @@ +$$plugins.define('select', ['domHelper'], function (element, options, $) { + var list = element.querySelector('.select__listWrap'), + selected = $('.select__button'), + selectedMob = element.querySelector('.select__button--mobile'), + input = element.querySelector('.select__input'), + options = $('.select__option'); + + function open() { + element.classList.add('select--open'); + $(list).slideDown(250); + } + + function close() { + $(list).slideUp(250, function () { + element.classList.remove('select--open'); + }); + } + + document.addEventListener('click', function (event) { + if (!isOpen() || element == event.target || $(event.target).parents().contains(element)) { + return; + } + close(); + }); + + selected.on("click", function (e) { + e.preventDefault(); + if (element.classList.contains('select--open')) { + close(); + } else { + open(); + } + }); + + function isOpen() { + return element.classList.contains('select--open'); + } + + options.on('click', function (e) { + e.target.classList.add('selected'); + prevActiveOption = Object.values(element.querySelectorAll('.selected')).filter(prevActive => prevActive !== e.target); + if (prevActiveOption.length != 0) { + prevActiveOption[0].classList.remove('selected'); + } + selected.text(e.target.innerHTML); + if (selectedMob) { + selectedMob.innerHTML = e.target.innerHTML; + } + $(input).val(e.target.dataset.value).trigger('change'); + close(); + }); +}); diff --git a/public/assets/js/forms/serialize.js b/public/assets/js/forms/serialize.js new file mode 100644 index 0000000..0bdd44c --- /dev/null +++ b/public/assets/js/forms/serialize.js @@ -0,0 +1,30 @@ +define(function () { + return function ($elements) { + var values = {}; + $elements.each(function () { + var $input = $(this); + var value = $input.val(); + if (!value) { + return; + } + if ($input.is(':checkbox, :radio') && !$input.is(':checked')) { + return; + } + var name = $(this).attr('name'); + var v = values[name] || []; + values[name] = v; + v.push(value); + }); + var s = ''; + for (var k in values) { + for (var i = 0; i < values[k].length; i++) { + s += '&' + k + '=' + encodeURIComponent(values[k][i]); + } + } + if (s) { + s = s.substr(1); + } + return s; + }; + +}); \ No newline at end of file diff --git a/public/assets/js/forms/textarea.js b/public/assets/js/forms/textarea.js new file mode 100644 index 0000000..493c78f --- /dev/null +++ b/public/assets/js/forms/textarea.js @@ -0,0 +1,26 @@ +$$plugins.define('textarea', function (element, options) { + const textarea = element.querySelector('textarea'); + + //style focus + textarea.addEventListener('focus', (event) => { + textarea.closest(".textarea").classList.add("focus"); + }); + + textarea.addEventListener('blur', (event) => { + textarea.closest(".textarea").classList.remove("focus"); + }); + + //characters count + textarea.addEventListener("input", event => { + const target = event.currentTarget; + const maxLength = target.getAttribute("maxlength"); + const currentLength = target.value.length; + const currentLengthText = document.getElementsByClassName("textarea__remaining")[0]; + + currentLengthText.innerHTML = currentLength; + + if (currentLength >= maxLength) { + return; + } + }); +}); diff --git a/public/assets/js/forms/validateform.js b/public/assets/js/forms/validateform.js new file mode 100644 index 0000000..38629e2 --- /dev/null +++ b/public/assets/js/forms/validateform.js @@ -0,0 +1,3 @@ +$.defineAttributePlugin('validateform', ['jQuery', 'jquery.validate', 'jquery.validate.unobtrusive', 'customValidators'], function ($element) { + $.validator.unobtrusive.parse($element); +}); \ No newline at end of file -- cgit v1.2.3