From c849a16c1090690e69d9a03c913c18d032857265 Mon Sep 17 00:00:00 2001 From: Ryan Wold <64987852+ryanwoldatwork@users.noreply.github.com> Date: Fri, 6 Dec 2024 12:21:01 -0800 Subject: [PATCH] remove legacy_form_embed * rename fba2 to fba --------- Co-authored-by: Shelley Nason --- app/controllers/admin/forms_controller.rb | 7 +- app/controllers/touchpoints_controller.rb | 6 +- app/models/form.rb | 7 +- app/views/admin/forms/_admin_options.html.erb | 15 - app/views/components/widget/_fba.js.erb | 249 +++---- app/views/components/widget/_fba2.js.erb | 686 ------------------ app/views/components/widget/_modal.html.erb | 51 +- .../components/widget/_no_modal.html.erb | 8 - app/views/components/widget/_widget.css.erb | 101 --- app/views/submissions/_form.html.erb | 6 +- ...20241024184630_remove_legacy_form_embed.rb | 5 + db/schema.rb | 1 - spec/features/embedded_touchpoints_spec.rb | 6 +- 13 files changed, 143 insertions(+), 1005 deletions(-) delete mode 100644 app/views/components/widget/_fba2.js.erb create mode 100644 db/migrate/20241024184630_remove_legacy_form_embed.rb diff --git a/app/controllers/admin/forms_controller.rb b/app/controllers/admin/forms_controller.rb index 9895deed3..dca3595a7 100644 --- a/app/controllers/admin/forms_controller.rb +++ b/app/controllers/admin/forms_controller.rb @@ -237,11 +237,7 @@ def example end def js - if @form.legacy_form_embed - render(partial: 'components/widget/fba', formats: :js, locals: { form: @form }) - else - render(partial: 'components/widget/fba2', formats: :js, locals: { form: @form }) - end + render(partial: 'components/widget/fba', formats: :js, locals: { form: @form }) end def new @@ -582,7 +578,6 @@ def form_admin_options_params :organization_id, :user_id, :template, - :legacy_form_embed, :kind, :aasm_state, :early_submission, diff --git a/app/controllers/touchpoints_controller.rb b/app/controllers/touchpoints_controller.rb index 91369f4e8..beca6ab0d 100644 --- a/app/controllers/touchpoints_controller.rb +++ b/app/controllers/touchpoints_controller.rb @@ -20,11 +20,7 @@ def show def js @form.increment!(:survey_form_activations) - if @form.legacy_form_embed || (params[:legacy] && params[:legacy] == '1') - render(partial: 'components/widget/fba', formats: :js, locals: { form: @form }) - else - render(partial: 'components/widget/fba2', formats: :js, locals: { form: @form }) - end + render(partial: 'components/widget/fba', formats: :js, locals: { form: @form }) end private diff --git a/app/models/form.rb b/app/models/form.rb index bcada6323..e837b0db2 100644 --- a/app/models/form.rb +++ b/app/models/form.rb @@ -225,7 +225,6 @@ def duplicate!(new_user:) new_form.legacy_touchpoint_uuid = nil new_form.notification_emails = nil new_form.organization = new_user.organization - new_form.legacy_form_embed = false new_form.template = false new_form.save! @@ -295,11 +294,7 @@ def deployable_form? # returns javascript text that can be used standalone # or injected into a GTM Container Tag def touchpoints_js_string - if self.legacy_form_embed - ApplicationController.new.render_to_string(partial: 'components/widget/fba', formats: :js, locals: { touchpoint: self }) - else - ApplicationController.new.render_to_string(partial: 'components/widget/fba2', formats: :js, locals: { touchpoint: self }) - end + ApplicationController.new.render_to_string(partial: 'components/widget/fba', formats: :js, locals: { form: self }) end def non_flagged_submissions(start_date: nil, end_date: nil) diff --git a/app/views/admin/forms/_admin_options.html.erb b/app/views/admin/forms/_admin_options.html.erb index 52b12cd68..4df07f9dd 100644 --- a/app/views/admin/forms/_admin_options.html.erb +++ b/app/views/admin/forms/_admin_options.html.erb @@ -54,21 +54,6 @@ -
-
- Form Template? -
- <%= f.check_box :legacy_form_embed, class: "usa-checkbox__input" %> - <%= f.label :legacy_form_embed, class: "usa-checkbox__label" do %> - Render legacy _fba.js.erb? -   - - Renders the old form as a fallback for certain clients who may have script customizations based on the old version. - - <% end %> -
-
-

<%= f.submit (@form.persisted? ? "Update Form Admin Options " : "Create Form"), class: "usa-button" %> diff --git a/app/views/components/widget/_fba.js.erb b/app/views/components/widget/_fba.js.erb index f520907a9..d8c0abe4d 100644 --- a/app/views/components/widget/_fba.js.erb +++ b/app/views/components/widget/_fba.js.erb @@ -10,7 +10,6 @@ function FBAform(d, N) { formElement: function() { return this.formComponent().querySelector("form"); }, - activatedButton: null, // tracks a reference to the button that was clicked to open the modal isFormSubmitted: false, // defaults to false // enable Javascript experience javascriptIsEnabled: function() { @@ -34,7 +33,6 @@ function FBAform(d, N) { this.loadButton(); } this._bindEventListeners(); - this.dialogOpen = false; // initially false this.successState = false; // initially false this._pagination(); if (this.options.formSpecificScript) { @@ -49,15 +47,6 @@ function FBAform(d, N) { }, _bindEventListeners: function() { var self = this; - d.addEventListener('keyup', function (event) { - var x = event.keyCode; - if( x == 27 && self.dialogOpen == true) { - self.closeDialog(); - } - }); - d.addEventListener('click', function (event) { - self.openModalDialog(event); - }); const textareas = this.formComponent().querySelectorAll(".usa-textarea"); textareas.forEach(function(textarea) { @@ -83,49 +72,52 @@ function FBAform(d, N) { } }, _loadHtml: function() { - <%# inject the form interface for the `inline` delivery option, without a wrapper %> - if ((this.options.deliveryMethod && this.options.deliveryMethod === 'inline') && this.options.suppressSubmitButton) { - if (this.options.elementSelector) { - if(d.getElementById(this.options.elementSelector) != null) { - d.getElementById(this.options.elementSelector).innerHTML = this.options.htmlFormBodyNoModal(); - } - } - } else if (this.options.deliveryMethod && this.options.deliveryMethod === 'inline') { <%# inject the form interface for inline with the modal wrapper %> - if (this.options.elementSelector) { - if(d.getElementById(this.options.elementSelector) != null) { - d.getElementById(this.options.elementSelector).innerHTML = this.options.htmlFormBody(); - } + <%# inject the form interface for the `inline` delivery option, without a wrapper %> + if ((this.options.deliveryMethod && this.options.deliveryMethod === 'inline') && this.options.suppressSubmitButton) { + if (this.options.elementSelector) { + if(d.getElementById(this.options.elementSelector) != null) { + d.getElementById(this.options.elementSelector).innerHTML = this.options.htmlFormBodyNoModal(); } } - <%# inject the form interface for modal and custom-button-modal %> - if (this.options.deliveryMethod && (this.options.deliveryMethod === 'modal' || this.options.deliveryMethod === 'custom-button-modal')) { - this.dialogEl = d.createElement('div'); - this.dialogEl.setAttribute("hidden", true); - this.dialogEl.setAttribute("aria-hidden", true); - this.dialogEl.setAttribute('class', 'fba-modal'); - this.dialogEl.setAttribute('data-touchpoints-form-id', this.options.formId); - - this.dialogEl.innerHTML = this.options.htmlFormBody(); - d.body.appendChild(this.dialogEl); - - this.formComponent().querySelector('.fba-modal-close').addEventListener('click', this.handleDialogClose.bind(this), false); - } - var otherElements = this.formElement().querySelectorAll(".usa-input.other-option"); - for (var i = 0; i < otherElements.length; i++) { - otherElements[i].addEventListener('keyup', this.handleOtherOption.bind(this), false); - } - var phoneElements = this.formElement().querySelectorAll("input[type='tel']"); - for (var i = 0; i < phoneElements.length; i++) { - phoneElements[i].addEventListener('keyup', this.handlePhoneInput.bind(this), false); + } else if (this.options.deliveryMethod && this.options.deliveryMethod === 'inline') { <%# inject the form interface for inline with the modal wrapper %> + if (this.options.elementSelector) { + if(d.getElementById(this.options.elementSelector) != null) { + d.getElementById(this.options.elementSelector).classList.add('fba-inline-container'); + d.getElementById(this.options.elementSelector).innerHTML = this.options.htmlFormBody(); + } } - <%# add button behaviors for custom-button-modal %> - if (this.options.deliveryMethod && this.options.deliveryMethod === 'custom-button-modal') { - if (this.options.elementSelector) { - if(d.getElementById(this.options.elementSelector) != null) { - d.getElementById(this.options.elementSelector).addEventListener('click', this.handleButtonClick.bind(this), false); - } + } + <%# inject the form interface for modal and custom-button-modal %> + if (this.options.deliveryMethod && (this.options.deliveryMethod === 'modal' || this.options.deliveryMethod === 'custom-button-modal')) { + this.dialogEl = d.createElement('div'); + this.dialogEl.setAttribute('class', "<%= form.prefix "usa-modal" %> fba-modal"); + this.dialogEl.setAttribute('id', this.modalId()); + this.dialogEl.setAttribute('aria-labelledby', `fba-form-title-${this.options.formId}`); + this.dialogEl.setAttribute('aria-describedby', `fba-form-instructions-${this.options.formId}`); + this.dialogEl.setAttribute('data-touchpoints-form-id', this.options.formId); + + this.dialogEl.innerHTML = this.options.htmlFormBody(); + d.body.appendChild(this.dialogEl); + } + var otherElements = this.formElement().querySelectorAll(".usa-input.other-option"); + for (var i = 0; i < otherElements.length; i++) { + otherElements[i].addEventListener('keyup', this.handleOtherOption.bind(this), false); + } + var phoneElements = this.formElement().querySelectorAll("input[type='tel']"); + for (var i = 0; i < phoneElements.length; i++) { + phoneElements[i].addEventListener('keyup', this.handlePhoneInput.bind(this), false); + } + <%# add button behaviors for custom-button-modal %> + if (this.options.deliveryMethod && this.options.deliveryMethod === 'custom-button-modal') { + if (this.options.elementSelector) { + const customButtonEl = d.getElementById(this.options.elementSelector); + if (customButtonEl != null) { + customButtonEl.setAttribute('data-open-modal', ''); + customButtonEl.setAttribute('aria-controls', this.modalId()); + customButtonEl.addEventListener('click', () => d.dispatchEvent(new Event('onTouchpointsModalOpen'))); } } + } var formElement = this.formElement(); // returns 1 or more submit buttons within the Touchpoints form @@ -159,26 +151,6 @@ function FBAform(d, N) { alertErrorElement.setAttribute("hidden", true); alertErrorElementBody.innerHTML = ""; }, - openModalDialog: function(e) { - if (this.options.deliveryMethod && this.options.deliveryMethod === 'modal' ) { - if (this.dialogOpen && !e.target.closest('#fba-button') && !e.target.closest('.fba-modal-dialog')) { - this.closeDialog(); - } - } else if (this.options.deliveryMethod && this.options.deliveryMethod === 'custom-button-modal' ) { - if (this.dialogOpen && !e.target.closest('#' + this.options.elementSelector) && !e.target.closest('.fba-modal-dialog')) { - this.closeDialog(); - } - } - }, - handleButtonClick: function(e) { - e.preventDefault(); - this.activatedButton = e.target; - this.loadDialog(); - }, - handleDialogClose: function(e) { - e.preventDefault(); - this.closeDialog(); - }, handleOtherOption: function(e) { var selectorId = "#" + e.srcElement.getAttribute("data-option-id"); var other_val = e.target.value.replace(/,/g, ''); @@ -187,13 +159,13 @@ function FBAform(d, N) { option.value = other_val; }, handlePhoneInput: function(e) { - var number = e.srcElement.value.replace(/[^\d]/g, ''); - if (number.length == 7) { - number = number.replace(/(\d{3})(\d{4})/, "$1-$2"); - } else if (number.length == 10) { - number = number.replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3"); - } - e.srcElement.value = number; + var number = e.srcElement.value.replace(/[^\d]/g, ''); + if (number.length == 7) { + number = number.replace(/(\d{3})(\d{4})/, "$1-$2"); + } else if (number.length == 10) { + number = number.replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3"); + } + e.srcElement.value = number; }, handleEmailInput: function(e) { var EmailRegex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/; @@ -206,8 +178,8 @@ function FBAform(d, N) { showWarning($(this),"Please enter a valid email address"); } else { showValid($(this)); - } - e.srcElement.value = number; + } + e.srcElement.value = number; }, handleSubmitClick: function(e) { e.preventDefault(); @@ -251,17 +223,17 @@ function FBAform(d, N) { Array.prototype.forEach.call(requiredItems, function(item) { switch (item.type) { - case 'radio': - if (item.checked) delete(questions[item.name]); - break; - case 'checkbox': - if (item.checked) delete(questions[item.name]); - break; - case 'select-one': - if (item.selectedIndex > 0) delete(questions[item.name]); - break; - default: - if (item.value.length > 0) delete(questions[item.name]); + case 'radio': + if (item.checked) delete(questions[item.name]); + break; + case 'checkbox': + if (item.checked) delete(questions[item.name]); + break; + case 'select-one': + if (item.selectedIndex > 0) delete(questions[item.name]); + break; + default: + if (item.value.length > 0) delete(questions[item.name]); } }); for (var key in questions) { @@ -276,12 +248,12 @@ function FBAform(d, N) { // Build a dictionary of questions which require an answer Array.prototype.forEach.call(dateItems, function(item) { questions[item.name] = item }); Array.prototype.forEach.call(dateItems, function(item) { - if (item.value.length == 0) { - delete(questions[item.name]); - } else { - var isValidDate = Date.parse(item.value); - if (!isNaN(isValidDate)) delete(questions[item.name]); - } + if (item.value.length == 0) { + delete(questions[item.name]); + } else { + var isValidDate = Date.parse(item.value); + if (!isNaN(isValidDate)) delete(questions[item.name]); + } }); for (var key in questions) { this.showValidationError(questions[key], '<%= I18n.t 'form.field_is_invalid' %>'); @@ -295,12 +267,12 @@ function FBAform(d, N) { // Build a dictionary of questions which require an answer Array.prototype.forEach.call(emailItems, function(item) { questions[item.name] = item }); Array.prototype.forEach.call(emailItems, function(item) { - if (item.value.length == 0) { - delete(questions[item.name]); - } else { - var EmailRegex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/; - if (EmailRegex.test(item.value)) delete(questions[item.name]); - } + if (item.value.length == 0) { + delete(questions[item.name]); + } else { + var EmailRegex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/; + if (EmailRegex.test(item.value)) delete(questions[item.name]); + } }); for (var key in questions) { this.showValidationError(questions[key], '<%= I18n.t 'form.field_is_invalid' %>'); @@ -314,12 +286,12 @@ function FBAform(d, N) { // Build a dictionary of questions which require an answer Array.prototype.forEach.call(phoneItems, function(item) { questions[item.name] = item }); Array.prototype.forEach.call(phoneItems, function(item) { - if (item.value.length == 0) { - delete(questions[item.name]); - } else { - const PhoneRegex = /^\(\d{3}\) \d{3}-\d{4}$/; - if (PhoneRegex.test(item.value)) delete(questions[item.name]); - } + if (item.value.length == 0) { + delete(questions[item.name]); + } else { + const PhoneRegex = /^\(\d{3}\) \d{3}-\d{4}$/; + if (PhoneRegex.test(item.value)) delete(questions[item.name]); + } }); for (var key in questions) { this.showValidationError(questions[key], '<%= I18n.t 'form.field_is_invalid' %>'); @@ -386,7 +358,7 @@ function FBAform(d, N) { }, loadButton: function() { // Add a landmark for button - this.landmarkElement = d.createElement('aside'); + this.landmarkElement = d.createElement('div'); this.landmarkElement.setAttribute('aria-label', 'Feedback button'); this.landmarkElement.setAttribute('role', 'complementary'); @@ -398,9 +370,10 @@ function FBAform(d, N) { this.buttonEl.setAttribute('name', 'fba-button'); this.buttonEl.setAttribute('href', 'javascript:void(0)'); this.buttonEl.setAttribute('aria-haspopup', 'dialog'); - this.buttonEl.setAttribute('aria-controls', 'dialog'); - this.buttonEl.addEventListener('click', this.handleButtonClick.bind(this), false); + this.buttonEl.setAttribute('aria-controls', this.modalId()); + this.buttonEl.setAttribute('data-open-modal', ''); this.buttonEl.innerHTML = this.options.modalButtonText; + this.buttonEl.addEventListener('click', () => d.dispatchEvent(new Event('onTouchpointsModalOpen'))); this.landmarkElement.appendChild(this.buttonEl); d.body.appendChild(this.landmarkElement); @@ -422,22 +395,6 @@ function FBAform(d, N) { d.body.prepend(this.skipLink); } }, - // Used when in a modal - loadDialog: function() { - d.dispatchEvent(new Event('onTouchpointsModalOpen')); - this.formComponent().removeAttribute("hidden"); - this.formComponent().setAttribute('aria-hidden', false); - this.formComponent().focus() - this.dialogOpen = true; - }, - closeDialog: function() { - d.dispatchEvent(new Event('onTouchpointsModalClose')); - this.formComponent().setAttribute("hidden", true); - this.formComponent().setAttribute('aria-hidden', true); - <%# Focus on the activated button if it exists and has a focus method %> - this.activatedButton?.focus?.(); - this.dialogOpen = false; - }, sendFeedback: function() { d.dispatchEvent(new Event('onTouchpointsFormSubmission')); var form = this.formElement(); @@ -518,7 +475,7 @@ function FBAform(d, N) { var submitButton = formElement.querySelector("[type='submit']"); if (e.target.readyState === 4) { - if (e.target.status === 201) { // SUCCESS! + if (e.target.status === 201) { // SUCCESS! this.successState = true; d.dispatchEvent(new Event('onTouchpointsFormSubmissionSuccess')); this.isFormSubmitted = true; @@ -553,8 +510,8 @@ function FBAform(d, N) { } }, ajaxPost: function (form, callback) { - var url = form.action; - var xhr = new XMLHttpRequest(); + var url = form.action; + var xhr = new XMLHttpRequest(); // for each form question var params = this.options.questionParams(form); @@ -572,9 +529,9 @@ function FBAform(d, N) { xhr.onload = callback.bind(this); xhr.send(JSON.stringify({ "submission": params, - <%- if @form.verify_csrf? %> + <%- if form.verify_csrf? %> "authenticity_token": form.querySelector("#authenticity_token") ? - form.querySelector("#authenticity_token").value : null + form.querySelector("#authenticity_token").value : null <% end %> })); }, @@ -654,7 +611,10 @@ function FBAform(d, N) { } }.bind(self)) } - } + }, + modalId: function() { + return `fba-modal-${this.options.formId}`; + }, }; }; @@ -677,10 +637,10 @@ const touchpointFormOptions<%= form.short_uuid %> = { 'questionParams' : function(form) { return { <% form.questions.each do |question| %> - <% next unless question_type_javascript_params(question).present? %> - <%= question.answer_field %> : <%= raw question_type_javascript_params(question) %>, + <% next unless question_type_javascript_params(question).present? %> + <%= question.answer_field %> : <%= raw question_type_javascript_params(question) %>, <% end %> - } + } }, 'suppressUI' : <%= (local_assigns.has_key?(:suppress_ui) && suppress_ui) %>, 'suppressSubmitButton' : <%= form.suppress_submit_button %>, @@ -703,7 +663,24 @@ const touchpointFormOptions<%= form.short_uuid %> = { // Create an instance of a Touchpoints form object const touchpointForm<%= form.short_uuid %> = new FBAform(document, window).init(touchpointFormOptions<%= form.short_uuid %>); -// Include USWDS JS if required <%- if form.load_css && form.delivery_method != "touchpoints-hosted-only" %> + +// Load the USWDS JS, loads as module 'fbaUswds' in global scope <%= render partial: 'components/widget/widget-uswds', formats: :js %> + +// Initialize any USWDS components used in this form +(function () { + const formId = "touchpoints-form-<%= form.short_uuid %>"; + const fbaFormElement = document.querySelector(`#${formId}`); + if (fbaFormElement) { + fbaUswds.ComboBox.on(fbaFormElement); + fbaUswds.DatePicker.on(fbaFormElement); + } + const modalId = "fba-modal-<%= form.short_uuid %>"; + const fbaModalElement = document.querySelector(`#${modalId}`); + if (fbaModalElement) { + fbaUswds.Modal.on(fbaModalElement); + } +})(); + <% end %> \ No newline at end of file diff --git a/app/views/components/widget/_fba2.js.erb b/app/views/components/widget/_fba2.js.erb deleted file mode 100644 index d60af6cc7..000000000 --- a/app/views/components/widget/_fba2.js.erb +++ /dev/null @@ -1,686 +0,0 @@ -// Form components are namespaced under 'fba' = 'Feedback Analytics' -// Updated: July 2024 -'use strict'; - -function FBAform(d, N) { - return { - formComponent: function() { - return d.querySelector("[data-touchpoints-form-id='" + this.options.formId + "']") - }, - formElement: function() { - return this.formComponent().querySelector("form"); - }, - isFormSubmitted: false, // defaults to false - // enable Javascript experience - javascriptIsEnabled: function() { - var javascriptDisabledMessage = d.getElementsByClassName("javascript-disabled-message")[0]; - var touchpointForm = d.getElementsByClassName("touchpoint-form")[0]; - if (javascriptDisabledMessage) { - javascriptDisabledMessage.classList.add("hide"); - } - if (touchpointForm) { - touchpointForm.classList.remove("hide"); - } - }, - init: function(options) { - this.javascriptIsEnabled(); - this.options = options; - if (this.options.loadCSS) { - this._loadCss(); - } - this._loadHtml(); - if (!this.options.suppressUI && (this.options.deliveryMethod && this.options.deliveryMethod === 'modal')) { - this.loadButton(); - } - this._bindEventListeners(); - this.successState = false; // initially false - this._pagination(); - if (this.options.formSpecificScript) { - this.options.formSpecificScript(); - } - d.dispatchEvent(new CustomEvent('onTouchpointsFormLoaded', { - detail: { - formComponent: this - } - })); - return this; - }, - _bindEventListeners: function() { - var self = this; - - const textareas = this.formComponent().querySelectorAll(".usa-textarea"); - textareas.forEach(function(textarea) { - if (textarea.getAttribute("maxlength") != '0' && textarea.getAttribute("maxlength") != '10000') { - textarea.addEventListener("keyup", self.textCounter); - } - }); - - <%# only text fields; not email or telephone %> - const textFields = this.formComponent().querySelectorAll(".usa-input[type='text']"); - textFields.forEach(function(textField) { - if (textField.getAttribute("maxlength") != '0' && textField.getAttribute("maxlength") != '10000') { - textField.addEventListener("keyup", self.textCounter); - } - }); - - }, - _loadCss: function() { - if (this.options.loadCSS) { - var style = d.createElement('style'); - style.innerHTML = this.options.css; - d.head.appendChild(style); - } - }, - _loadHtml: function() { - <%# inject the form interface for the `inline` delivery option, without a wrapper %> - if ((this.options.deliveryMethod && this.options.deliveryMethod === 'inline') && this.options.suppressSubmitButton) { - if (this.options.elementSelector) { - if(d.getElementById(this.options.elementSelector) != null) { - d.getElementById(this.options.elementSelector).innerHTML = this.options.htmlFormBodyNoModal(); - } - } - } else if (this.options.deliveryMethod && this.options.deliveryMethod === 'inline') { <%# inject the form interface for inline with the modal wrapper %> - if (this.options.elementSelector) { - if(d.getElementById(this.options.elementSelector) != null) { - d.getElementById(this.options.elementSelector).classList.add('fba-inline-container'); - d.getElementById(this.options.elementSelector).innerHTML = this.options.htmlFormBody(); - } - } - } - <%# inject the form interface for modal and custom-button-modal %> - if (this.options.deliveryMethod && (this.options.deliveryMethod === 'modal' || this.options.deliveryMethod === 'custom-button-modal')) { - this.dialogEl = d.createElement('div'); - this.dialogEl.setAttribute('class', "<%= form.prefix "usa-modal" %> fba-modal"); - this.dialogEl.setAttribute('id', this.modalId()); - this.dialogEl.setAttribute('aria-labelledby', `fba-form-title-${this.options.formId}`); - this.dialogEl.setAttribute('aria-describedby', `fba-form-instructions-${this.options.formId}`); - this.dialogEl.setAttribute('data-touchpoints-form-id', this.options.formId); - - this.dialogEl.innerHTML = this.options.htmlFormBody(); - d.body.appendChild(this.dialogEl); - } - var otherElements = this.formElement().querySelectorAll(".usa-input.other-option"); - for (var i = 0; i < otherElements.length; i++) { - otherElements[i].addEventListener('keyup', this.handleOtherOption.bind(this), false); - } - var phoneElements = this.formElement().querySelectorAll("input[type='tel']"); - for (var i = 0; i < phoneElements.length; i++) { - phoneElements[i].addEventListener('keyup', this.handlePhoneInput.bind(this), false); - } - <%# add button behaviors for custom-button-modal %> - if (this.options.deliveryMethod && this.options.deliveryMethod === 'custom-button-modal') { - if (this.options.elementSelector) { - const customButtonEl = d.getElementById(this.options.elementSelector); - if (customButtonEl != null) { - customButtonEl.setAttribute('data-open-modal', ''); - customButtonEl.setAttribute('aria-controls', this.modalId()); - customButtonEl.addEventListener('click', () => d.dispatchEvent(new Event('onTouchpointsModalOpen'))); - } - } - } - - var formElement = this.formElement(); - // returns 1 or more submit buttons within the Touchpoints form - var submitButtons = formElement.querySelectorAll("[type='submit']"); - var that = this; - - var yesNoForm = formElement.querySelector('.touchpoints-yes-no-buttons'); - - if (yesNoForm) { // only for yes/no questions - Array.prototype.forEach.call(submitButtons, function(submitButton) { - submitButton.addEventListener('click', that.handleYesNoSubmitClick.bind(that), false); - }) - } else { // for all other types of forms/questions - if (submitButtons) { - Array.prototype.forEach.call(submitButtons, function(submitButton) { - submitButton.addEventListener('click', that.handleSubmitClick.bind(that), false); - }) - } - } - }, - resetErrors: function() { - var formComponent = this.formComponent(); - var alertElement = formComponent.querySelector(".fba-alert"); - var alertElementHeading = formComponent.getElementsByClassName("usa-alert__heading")[0]; - var alertElementBody = formComponent.getElementsByClassName("usa-alert__text")[0]; - var alertErrorElement = formComponent.querySelector(".fba-alert-error"); - var alertErrorElementBody = alertErrorElement.getElementsByClassName("usa-alert__text")[0]; - alertElement.setAttribute("hidden", true); - alertElementHeading.innerHTML = ""; - alertElementBody.innerHTML = ""; - alertErrorElement.setAttribute("hidden", true); - alertErrorElementBody.innerHTML = ""; - }, - handleOtherOption: function(e) { - var selectorId = "#" + e.srcElement.getAttribute("data-option-id"); - var other_val = e.target.value.replace(/,/g, ''); - if (other_val == '') other_val = 'other'; - var option = this.formElement().querySelector(selectorId); - option.value = other_val; - }, - handlePhoneInput: function(e) { - var number = e.srcElement.value.replace(/[^\d]/g, ''); - if (number.length == 7) { - number = number.replace(/(\d{3})(\d{4})/, "$1-$2"); - } else if (number.length == 10) { - number = number.replace(/(\d{3})(\d{3})(\d{4})/, "($1) $2-$3"); - } - e.srcElement.value = number; - }, - handleEmailInput: function(e) { - var EmailRegex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/; - var email = e.srcElement.value.trim(); - if (email.length == 0) { - return; - } - result = EmailRegex.test(email); - if (!result) { - showWarning($(this),"Please enter a valid email address"); - } else { - showValid($(this)); - } - e.srcElement.value = number; - }, - handleSubmitClick: function(e) { - e.preventDefault(); - this.resetErrors(); - var formElement = this.formElement(); - var self = this; - if (self.validateForm(formElement)) { - // disable submit button and show sending feedback message - var submitButton = formElement.querySelector("[type='submit']"); - submitButton.disabled = true; - submitButton.classList.add("aria-disabled"); - self.sendFeedback(); - } - }, - handleYesNoSubmitClick: function(e) { - e.preventDefault(); - - var input = this.formComponent().querySelector('.fba-touchpoints-page-form'); - input.value = e.target.value; - this.resetErrors(); - var self = this; - var formElement = this.formElement(); - if (self.validateForm(formElement)) { - var submitButtons = formElement.querySelectorAll("[type='submit']"); - Array.prototype.forEach.call(submitButtons, function(submitButton) { - submitButton.disabled = true; - }) - self.sendFeedback(); - } - }, - validateForm: function(form) { - this.hideValidationError(form); - var valid = this.checkRequired(form) && this.checkEmail(form) && this.checkPhone(form) && this.checkDate(form); - return valid; - }, - checkRequired: function(form) { - var requiredItems = form.querySelectorAll('[required]'); - var questions = {}; - // Build a dictionary of questions which require an answer - Array.prototype.forEach.call(requiredItems, function(item) { questions[item.name] = item }); - - Array.prototype.forEach.call(requiredItems, function(item) { - switch (item.type) { - case 'radio': - if (item.checked) delete(questions[item.name]); - break; - case 'checkbox': - if (item.checked) delete(questions[item.name]); - break; - case 'select-one': - if (item.selectedIndex > 0) delete(questions[item.name]); - break; - default: - if (item.value.length > 0) delete(questions[item.name]); - } - }); - for (var key in questions) { - this.showValidationError(questions[key], '<%= I18n.t 'form.field_is_required' %>'); - return false; - } - return true; - }, - checkDate: function(form) { - var dateItems = form.querySelectorAll('.date-select'); - var questions = {}; - // Build a dictionary of questions which require an answer - Array.prototype.forEach.call(dateItems, function(item) { questions[item.name] = item }); - Array.prototype.forEach.call(dateItems, function(item) { - if (item.value.length == 0) { - delete(questions[item.name]); - } else { - var isValidDate = Date.parse(item.value); - if (!isNaN(isValidDate)) delete(questions[item.name]); - } - }); - for (var key in questions) { - this.showValidationError(questions[key], '<%= I18n.t 'form.field_is_invalid' %>'); - return false; - } - return true; - }, - checkEmail: function(form) { - var emailItems = form.querySelectorAll('input[type="email"]'); - var questions = {}; - // Build a dictionary of questions which require an answer - Array.prototype.forEach.call(emailItems, function(item) { questions[item.name] = item }); - Array.prototype.forEach.call(emailItems, function(item) { - if (item.value.length == 0) { - delete(questions[item.name]); - } else { - var EmailRegex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/; - if (EmailRegex.test(item.value)) delete(questions[item.name]); - } - }); - for (var key in questions) { - this.showValidationError(questions[key], '<%= I18n.t 'form.field_is_invalid' %>'); - return false; - } - return true; - }, - checkPhone: function(form) { - var phoneItems = form.querySelectorAll('input[type="tel"]'); - var questions = {}; - // Build a dictionary of questions which require an answer - Array.prototype.forEach.call(phoneItems, function(item) { questions[item.name] = item }); - Array.prototype.forEach.call(phoneItems, function(item) { - if (item.value.length == 0) { - delete(questions[item.name]); - } else { - const PhoneRegex = /^\(\d{3}\) \d{3}-\d{4}$/; - if (PhoneRegex.test(item.value)) delete(questions[item.name]); - } - }); - for (var key in questions) { - this.showValidationError(questions[key], '<%= I18n.t 'form.field_is_invalid' %>'); - return false; - } - return true; - }, - showValidationError: function(question, error) { - var questionDiv = question.closest(".question"); - var label = questionDiv.querySelector(".usa-label") || questionDiv.querySelector(".usa-legend"); - var questionNum = label.innerText; - - // show page with validation error - var errorPage = question.closest(".section"); - if (!errorPage.classList.contains("fba-visible")) { - var visiblePage = this.formComponent().getElementsByClassName("section fba-visible")[0]; - visiblePage.classList.remove("fba-visible"); - errorPage.classList.add("fba-visible"); - } - - questionDiv.setAttribute('class', 'usa-form-group usa-form-group--error'); - var span = d.createElement('span'); - span.setAttribute('id', 'input-error-message'); - span.setAttribute('role','alert'); - span.setAttribute('class','usa-error-message'); - span.innerText = error + questionNum; - label.parentNode.insertBefore(span, label.nextSibling); - var input = d.createElement('input'); - input.setAttribute('hidden', 'true'); - input.setAttribute('id','input-error'); - input.setAttribute('type','text'); - input.setAttribute('name','input-error'); - input.setAttribute('aria-describedby','input-error-message'); - questionDiv.appendChild(input); - questionDiv.scrollIntoView(); - questionDiv.focus(); - - // enable submit button ( so user can fix error and resubmit ) - var submitButton = this.formComponent().querySelector("[type='submit']"); - submitButton.disabled = false; - submitButton.classList.remove("aria-disabled"); - }, - hideValidationError: function(form) { - var elem = form.querySelector('.usa-form-group--error'); - if (elem == null) return; - elem.setAttribute('class','question'); - var elem = form.querySelector('#input-error-message'); - if (elem != null) elem.parentNode.removeChild(elem); - elem = form.querySelector('#input-error'); - if (elem != null) elem.parentNode.removeChild(elem); - }, - textCounter: function(event) { - const field = event.target; - const maxLimit = event.target.getAttribute("maxlength"); - - var countfield = field.parentNode.querySelector(".counter-msg"); - if (field.value.length > maxLimit) { - field.value = field.value.substring(0, maxLimit); - countfield.innerText = '0 <%= t :characters_left %>'; - return false; - } else { - countfield.innerText = "" + (maxLimit - field.value.length) + " <%= t :characters_left %>"; - } - }, - loadButton: function() { - // Add a landmark for button - this.landmarkElement = d.createElement('div'); - this.landmarkElement.setAttribute('aria-label', 'Feedback button'); - this.landmarkElement.setAttribute('role', 'complementary'); - - // Add the fixed, floating tab button - this.buttonEl = d.createElement('a'); - this.buttonEl.setAttribute('id', 'fba-button'); - this.buttonEl.setAttribute('data-id', this.options.formId); - this.buttonEl.setAttribute('class', 'fba-button fixed-tab-button usa-button'); - this.buttonEl.setAttribute('name', 'fba-button'); - this.buttonEl.setAttribute('href', 'javascript:void(0)'); - this.buttonEl.setAttribute('aria-haspopup', 'dialog'); - this.buttonEl.setAttribute('aria-controls', this.modalId()); - this.buttonEl.setAttribute('data-open-modal', ''); - this.buttonEl.innerHTML = this.options.modalButtonText; - this.buttonEl.addEventListener('click', () => d.dispatchEvent(new Event('onTouchpointsModalOpen'))); - this.landmarkElement.appendChild(this.buttonEl); - d.body.appendChild(this.landmarkElement); - - this.loadFeebackSkipLink(); - }, - loadFeebackSkipLink: function() { - this.skipLink = d.createElement('a'); - this.skipLink.setAttribute('class', 'usa-skipnav touchpoints-skipnav'); - this.skipLink.setAttribute('href', '#fba-button'); - this.skipLink.addEventListener('click', function() { - d.querySelector("#fba-button").focus(); - }); - this.skipLink.innerHTML = 'Skip to feedback'; - - var existingSkipLinks = d.querySelector('.usa-skipnav'); - if(existingSkipLinks) { - existingSkipLinks.insertAdjacentElement('afterend', this.skipLink); - } else { - d.body.prepend(this.skipLink); - } - }, - sendFeedback: function() { - d.dispatchEvent(new Event('onTouchpointsFormSubmission')); - var form = this.formElement(); - this.ajaxPost(form, this.formSuccess); - }, - successHeadingText: function() { - return this.options.successTextHeading; - }, - successText: function() { - return this.options.successText; - }, - showFormSuccess: function(e) { - var formComponent = this.formComponent(); - var formElement = this.formElement(); - var alertElement = formComponent.querySelector(".fba-alert"); - var alertElementHeading = formComponent.querySelector(".usa-alert__heading"); - var alertElementBody = formComponent.querySelector(".usa-alert__text"); - - // Display success Message - alertElementHeading.innerHTML += this.successHeadingText(); - alertElementBody.innerHTML = this.successText(); - alertElement.removeAttribute("hidden"); - this.formComponent().scrollIntoView(); - - // Hide Form Elements - if (formElement) { - // And clear the Form's Fields - formElement.reset(); - if (formElement.querySelector('.touchpoints-form-body')) { - var formBody = formElement.querySelector('.touchpoints-form-body'); - if(formBody) { - formBody.setAttribute("hidden", true); - } - } - if (formComponent.querySelector('.touchpoints-form-disclaimer')) { - var formDisclaimer = formComponent.querySelector('.touchpoints-form-disclaimer'); - if(formDisclaimer) { - formDisclaimer.setAttribute("hidden", true); - } - } - - } - }, - resetFormDisplay: function() { - if (this.successState === false) { - return false; - } - - // Hide and Reset Flash Message - this.resetErrors(); - - // Re-enable Submit Button - var formElement = this.formElement(); - var submitButton = formElement.querySelector("[type='submit']"); - submitButton.disabled = false; - - // Show Form Elements - if (formElement) { - if (formElement.querySelector('.touchpoints-form-body')) { - var formBody = formElement.querySelector('.touchpoints-form-body') - if(formBody) { - formBody.removeAttribute("hidden"); - } - } - } - }, - formSuccess: function(e) { - // Clear the alert box - var formComponent = this.formComponent(); - var alertElement = formComponent.querySelector(".fba-alert"); - var alertElementBody = formComponent.getElementsByClassName("usa-alert__text")[0]; - var alertErrorElement = formComponent.querySelector(".fba-alert-error"); - var alertErrorElementBody = alertErrorElement.getElementsByClassName("usa-alert__text")[0]; - alertElementBody.innerHTML = ""; - alertErrorElementBody.innerHTML = ""; - - var formElement = this.formElement(); - var submitButton = formElement.querySelector("[type='submit']"); - - if (e.target.readyState === 4) { - if (e.target.status === 201) { // SUCCESS! - this.successState = true; - d.dispatchEvent(new Event('onTouchpointsFormSubmissionSuccess')); - this.isFormSubmitted = true; - if(submitButton) { - submitButton.disabled = true; - } - this.showFormSuccess(); - } else if (e.target.status === 422) { // FORM ERRORS - this.successState = false; - d.dispatchEvent(new Event('onTouchpointsFormSubmissionError')); - if(submitButton) { - submitButton.disabled = false; - } - - var jsonResponse = JSON.parse(e.target.response); - var errors = jsonResponse.messages; - - for (var err in errors) { - if (errors.hasOwnProperty(err)) { - alertErrorElementBody.innerHTML += err; - alertErrorElementBody.innerHTML += " "; - alertErrorElementBody.innerHTML += errors[err]; - alertErrorElementBody.innerHTML += "
"; - } - } - - alertErrorElement.removeAttribute("hidden"); - } else { // OTHER SERVER ERROR - alertErrorElement.removeAttribute("hidden"); - alertErrorElementBody.innerHTML += "Server error. We're sorry, but this submission was not successful. The Product Team has been notified."; - } - } - }, - ajaxPost: function (form, callback) { - var url = form.action; - var xhr = new XMLHttpRequest(); - // for each form question - var params = this.options.questionParams(form); - - // Combine Referrer and Pathname with Form-specific params - params["referer"] = d.referrer; - params["hostname"] = N.location.hostname; - params["page"] = N.location.pathname; - params["location_code"] = form.querySelector("#fba_location_code") ? form.querySelector("#fba_location_code").value : null; - params["fba_directive"] = form.querySelector("#fba_directive") ? form.querySelector("#fba_directive").value : null; - params["language"] = "en"; - - // Submit Feedback with a POST - xhr.open("POST", url); - xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8;"); - xhr.onload = callback.bind(this); - xhr.send(JSON.stringify({ - "submission": params, - <%- if @form.verify_csrf? %> - "authenticity_token": form.querySelector("#authenticity_token") ? - form.querySelector("#authenticity_token").value : null - <% end %> - })); - }, - currentPageNumber: 1, // start at 1 - showInstructions: function() { - const instructions = this.formComponent().getElementsByClassName("fba-instructions")[0]; - - if(instructions) { - if (this.currentPageNumber == 1) { - instructions.removeAttribute("hidden"); - } else { - instructions.setAttribute("hidden", true); - } - } - - const requiredQuestionsNotice = this.formComponent().getElementsByClassName("required-questions-notice")[0]; - if(requiredQuestionsNotice) { - if (this.currentPageNumber == 1) { - requiredQuestionsNotice.removeAttribute("hidden"); - } else { - requiredQuestionsNotice.setAttribute("hidden", true); - } - } - }, - _pagination: function() { - var previousButtons = this.formComponent().getElementsByClassName("previous-section"); - var nextButtons = this.formComponent().getElementsByClassName("next-section"); - - var self = this; - for (var i = 0; i < previousButtons.length; i++) { - previousButtons[i].addEventListener('click', function(e) { - e.preventDefault(); - var currentPage = e.target.closest(".section"); - if (!this.validateForm(currentPage)) return false; - currentPage.classList.remove("fba-visible"); - this.currentPageNumber--; - this.showInstructions(); - currentPage.previousElementSibling.classList.add("fba-visible"); - - const previousPageEvent = new CustomEvent('onTouchpointsFormPreviousPage', { - detail: { - formComponent: this - } - }); - d.dispatchEvent(previousPageEvent); - - // if in a modal, scroll to the top of the modal on previous button click - if(this.formComponent().getElementsByClassName("fba-modal")[0]) { - this.formComponent().scrollTo(0,0); - } else { - N.scrollTo(0, 0); - } - }.bind(self)); - } - for (var i = 0; i < nextButtons.length; i++) { - nextButtons[i].addEventListener('click', function(e) { - e.preventDefault(); - var currentPage = e.target.closest(".section"); - if (!this.validateForm(currentPage)) return false; - currentPage.classList.remove("fba-visible"); - this.currentPageNumber++; - this.showInstructions(); - currentPage.nextElementSibling.classList.add("fba-visible"); - - const nextPageEvent = new CustomEvent('onTouchpointsFormNextPage', { - detail: { - formComponent: this - } - }); - d.dispatchEvent(nextPageEvent); - - // if in a modal, scroll to the top of the modal on next button click - if(this.formComponent().getElementsByClassName("fba-modal")[0]) { - this.formComponent().scrollTo(0,0); - } else { - N.scrollTo(0, 0); - } - }.bind(self)) - } - }, - modalId: function() { - return `fba-modal-${this.options.formId}`; - }, - }; -}; - -// Specify the options for your form -const touchpointFormOptions<%= form.short_uuid %> = { - 'formId': "<%= form.short_uuid %>", - 'modalButtonText': "<%= form.modal_button_text %>", - 'elementSelector': "<%= form.element_selector %>", - 'css' : "<%= escape_javascript(render partial: 'components/widget/widget', formats: :css, locals: { form: form }) %>", - 'loadCSS' : <%= form.load_css %>, - 'formSpecificScript' : function() { - <%- if ["a11_v2", "a11_yes_no"].include?(form.kind) %> - <%= render "components/form_#{form.kind}_script", form: form %> - <% end %> - }, - 'deliveryMethod' : "<%= form.delivery_method %>", - 'successTextHeading' : "<%= escape_javascript(form.success_text_heading) %>", - 'successText' : "<%= escape_javascript(sanitize(form.success_text)) %>", - <%# Dynamically write the Form parameters for Custom Forms %> - 'questionParams' : function(form) { - return { - <% form.questions.each do |question| %> - <% next unless question_type_javascript_params(question).present? %> - <%= question.answer_field %> : <%= raw question_type_javascript_params(question) %>, - <% end %> - } - }, - 'suppressUI' : <%= (local_assigns.has_key?(:suppress_ui) && suppress_ui) %>, - 'suppressSubmitButton' : <%= form.suppress_submit_button %>, - 'htmlFormBody' : function() { - <%- if (form.delivery_method == "inline" && !form.suppress_submit_button && form.element_selector?) || form.delivery_method == "modal" || form.delivery_method == "custom-button-modal" %> - return "<%= escape_javascript render(partial: 'components/widget/modal', locals: { form: form }) %>"; - <% else %> - return null; - <% end %> - }, - 'htmlFormBodyNoModal' : function() { - <%- if form.delivery_method == "inline" && form.suppress_submit_button && form.element_selector? %> - return "<%= escape_javascript render(partial: 'components/widget/no_modal', locals: { form: form }) %>"; - <% else %> - return null; - <% end %> - } -} - -// Create an instance of a Touchpoints form object -const touchpointForm<%= form.short_uuid %> = new FBAform(document, window).init(touchpointFormOptions<%= form.short_uuid %>); - -<%- if form.load_css && form.delivery_method != "touchpoints-hosted-only" %> - -// Load the USWDS JS, loads as module 'fbaUswds' in global scope -<%= render partial: 'components/widget/widget-uswds', formats: :js %> - -// Initialize any USWDS components used in this form -(function () { - const formId = "touchpoints-form-<%= form.short_uuid %>"; - const fbaFormElement = document.querySelector(`#${formId}`); - if (fbaFormElement) { - fbaUswds.ComboBox.on(fbaFormElement); - fbaUswds.DatePicker.on(fbaFormElement); - } - const modalId = "fba-modal-<%= form.short_uuid %>"; - const fbaModalElement = document.querySelector(`#${modalId}`); - if (fbaModalElement) { - fbaUswds.Modal.on(fbaModalElement); - } -})(); - -<% end %> \ No newline at end of file diff --git a/app/views/components/widget/_modal.html.erb b/app/views/components/widget/_modal.html.erb index 22193f973..698fb77ca 100644 --- a/app/views/components/widget/_modal.html.erb +++ b/app/views/components/widget/_modal.html.erb @@ -1,34 +1,21 @@ -<%- if form.legacy_form_embed %> -

-<% else %> -
fba-modal-dialog"> -
-
padding-bottom-0 padding-top-0"> - <%= render "components/widget/no_modal", form: form %> -
- <%= render partial: 'components/forms/footer', locals: { form: form } %> +
fba-modal-dialog"> +
+
padding-bottom-0 padding-top-0"> + <%= render "components/widget/no_modal", form: form %>
- <%- unless form.delivery_method == "inline" %> - - <% end -%> + <%= render partial: 'components/forms/footer', locals: { form: form } %>
-<% end %> \ No newline at end of file + <%- unless form.delivery_method == "inline" %> + + <% end -%> +
diff --git a/app/views/components/widget/_no_modal.html.erb b/app/views/components/widget/_no_modal.html.erb index a9b749431..3e904f42f 100644 --- a/app/views/components/widget/_no_modal.html.erb +++ b/app/views/components/widget/_no_modal.html.erb @@ -4,14 +4,6 @@ data-touchpoints-form-id="<%= form.short_uuid %>" >
- <%- if form.legacy_form_embed %> - <%- unless form.delivery_method == "inline" %> - × - <% end -%> - <% end %> <%- unless form.archived? %> <%= render "components/forms/logo_and_title", form: form %> <%- if form.instructions? %> diff --git a/app/views/components/widget/_widget.css.erb b/app/views/components/widget/_widget.css.erb index cb8306ed0..155eeddd6 100644 --- a/app/views/components/widget/_widget.css.erb +++ b/app/views/components/widget/_widget.css.erb @@ -1,103 +1,3 @@ -<%- if form.legacy_form_embed %> -.fba-modal { - background-color: rgb(0, 0, 0, 0.375); - z-index: 10001; - height: 100%; - position: fixed; - top: 0; - left: 0; - right: 0; - overflow-x: auto; - padding: 20px; -} - -.fba-modal-dialog { - background: #fff; - border: 1px solid #E5E5E5; - margin: 0 auto 40px auto; - max-width: 35rem; - position: relative; -} - -.fba-modal-dialog h1 { - margin-right: 20px; - word-wrap: break-word; -} - -.fba-modal-dialog .touchpoints-inner-form-wrapper { - padding-left: 20px; - padding-right: 20px; -} - -.fba-modal-dialog .fba-modal-close { - position: absolute; - top: 0; - right: 0; - padding: 10px; - font-size: 24px; - color: #5b616b; - background: none; - line-height: 1; - text-decoration: none; - width: auto; - z-index: 10; -} - -/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ -.fba-modal-dialog html{ - font-family:sans-serif; - -ms-text-size-adjust:100%; - -webkit-text-size-adjust:100%; -} -.fba-modal-dialog body{ - margin:0; -} - -.fba-modal-dialog *, -.fba-modal-dialog *::before, -.fba-modal-dialog *::after{ - -webkit-box-sizing:inherit; - box-sizing:inherit; -} - -.fba-modal-dialog { - background-color:white; - color:#1b1b1b; - overflow-x:hidden; - -webkit-font-feature-settings:'kern' 1; - font-feature-settings:'kern' 1; - -webkit-font-kerning:normal; - font-kerning:normal; - font-family:Source Sans Pro Web, Helvetica Neue, Helvetica, Roboto, Arial, sans-serif; - font-size:100%; - -webkit-box-sizing:border-box; - box-sizing:border-box; -} - -.fba-modal-dialog .usa-overlay{ - position:absolute; - bottom:0; - left:0; - right:0; - top:0; - position:fixed; - background:black; - opacity:0; - transition:opacity 0.2s ease-in-out; - visibility:hidden; - z-index:400; -} - -.fba-modal-dialog .usa-overlay.is-visible{ - opacity:0.2; - visibility:visible; -} - -/* Override */ -.fba-modal-dialog .usa-form { - max-width: inherit; -} -<% else %> .fba-modal-dialog { font-family: Source Sans Pro Web, Helvetica Neue, Helvetica, Roboto, Arial, sans-serif; font-size: 100%; @@ -108,7 +8,6 @@ margin-top: -1rem; word-wrap: break-word; } -<% end %> .fba-inline-container { background: #fff; diff --git a/app/views/submissions/_form.html.erb b/app/views/submissions/_form.html.erb index c14409ece..a689752f5 100644 --- a/app/views/submissions/_form.html.erb +++ b/app/views/submissions/_form.html.erb @@ -1,8 +1,4 @@ <%= render "components/forms/custom_layout", form: form, questions: form.ordered_questions %> diff --git a/db/migrate/20241024184630_remove_legacy_form_embed.rb b/db/migrate/20241024184630_remove_legacy_form_embed.rb new file mode 100644 index 000000000..f8d556ec0 --- /dev/null +++ b/db/migrate/20241024184630_remove_legacy_form_embed.rb @@ -0,0 +1,5 @@ +class RemoveLegacyFormEmbed < ActiveRecord::Migration[7.1] + def change + remove_column :forms, :legacy_form_embed + end +end diff --git a/db/schema.rb b/db/schema.rb index 770d5877f..4d40bf6f9 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -306,7 +306,6 @@ t.string "submission_tags", default: [], comment: "cache the form's submissions tags for reporting", array: true t.datetime "submitted_at" t.datetime "approved_at" - t.boolean "legacy_form_embed", default: false t.datetime "archived_at" t.string "audience", default: "public", comment: "indicates whether a form is intended for a public or internal audience" t.string "short_uuid", limit: 8 diff --git a/spec/features/embedded_touchpoints_spec.rb b/spec/features/embedded_touchpoints_spec.rb index 2d9120e1a..a08b49edd 100644 --- a/spec/features/embedded_touchpoints_spec.rb +++ b/spec/features/embedded_touchpoints_spec.rb @@ -6,9 +6,8 @@ let(:organization) { FactoryBot.create(:organization) } let!(:user) { FactoryBot.create(:user, :admin, organization:) } - [true, false].each do |val| - context "as Admin with legacy_form_embed #{val}" do - let!(:form) { FactoryBot.create(:form, :kitchen_sink, legacy_form_embed: val, organization:) } + context "as Admin" do + let!(:form) { FactoryBot.create(:form, :kitchen_sink, organization:) } describe '/forms/:id/example' do before do @@ -97,5 +96,4 @@ end end end - end end