diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index d43eae7973080b107e405612b86349ed266ae924..1de875adf708daece287fdc99905e738b0de2489 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -79,6 +79,8 @@ import initChangesDropdown from './init_changes_dropdown'; import AbuseReports from './abuse_reports'; import { ajaxGet, convertPermissionToBoolean } from './lib/utils/common_utils'; import AjaxLoadingSpinner from './ajax_loading_spinner'; +import GlFieldErrors from './gl_field_errors'; +import GLForm from './gl_form'; import U2FAuthenticate from './u2f/authenticate'; (function() { @@ -230,7 +232,7 @@ import U2FAuthenticate from './u2f/authenticate'; case 'groups:milestones:update': new ZenMode(); new gl.DueDateSelectors(); - new gl.GLForm($('.milestone-form'), true); + new GLForm($('.milestone-form'), true); break; case 'projects:compare:show': new gl.Diff(); @@ -247,7 +249,7 @@ import U2FAuthenticate from './u2f/authenticate'; case 'projects:issues:new': case 'projects:issues:edit': shortcut_handler = new ShortcutsNavigation(); - new gl.GLForm($('.issue-form'), true); + new GLForm($('.issue-form'), true); new IssuableForm($('.issue-form')); new LabelsSelect(); new MilestoneSelect(); @@ -271,7 +273,7 @@ import U2FAuthenticate from './u2f/authenticate'; case 'projects:merge_requests:edit': new gl.Diff(); shortcut_handler = new ShortcutsNavigation(); - new gl.GLForm($('.merge-request-form'), true); + new GLForm($('.merge-request-form'), true); new IssuableForm($('.merge-request-form')); new LabelsSelect(); new MilestoneSelect(); @@ -280,7 +282,7 @@ import U2FAuthenticate from './u2f/authenticate'; break; case 'projects:tags:new': new ZenMode(); - new gl.GLForm($('.tag-form'), true); + new GLForm($('.tag-form'), true); new RefSelectDropdown($('.js-branch-select')); break; case 'projects:snippets:show': @@ -290,17 +292,17 @@ import U2FAuthenticate from './u2f/authenticate'; case 'projects:snippets:edit': case 'projects:snippets:create': case 'projects:snippets:update': - new gl.GLForm($('.snippet-form'), true); + new GLForm($('.snippet-form'), true); break; case 'snippets:new': case 'snippets:edit': case 'snippets:create': case 'snippets:update': - new gl.GLForm($('.snippet-form'), false); + new GLForm($('.snippet-form'), false); break; case 'projects:releases:edit': new ZenMode(); - new gl.GLForm($('.release-form'), true); + new GLForm($('.release-form'), true); break; case 'projects:merge_requests:show': new gl.Diff(); @@ -606,7 +608,7 @@ import U2FAuthenticate from './u2f/authenticate'; new Wikis(); shortcut_handler = new ShortcutsWiki(); new ZenMode(); - new gl.GLForm($('.wiki-form'), true); + new GLForm($('.wiki-form'), true); break; case 'snippets': shortcut_handler = new ShortcutsNavigation(); @@ -657,7 +659,7 @@ import U2FAuthenticate from './u2f/authenticate'; Dispatcher.prototype.initFieldErrors = function() { $('.gl-show-field-errors').each((i, form) => { - new gl.GlFieldErrors(form); + new GlFieldErrors(form); }); }; diff --git a/app/assets/javascripts/gl_field_error.js b/app/assets/javascripts/gl_field_error.js index 0add707525498f40cbda8cb0e80a8128c3decb47..bd63f6f16f07013cfb60374c5bb610b5322814a5 100644 --- a/app/assets/javascripts/gl_field_error.js +++ b/app/assets/javascripts/gl_field_error.js @@ -54,7 +54,7 @@ const inputErrorClass = 'gl-field-error-outline'; const errorAnchorSelector = '.gl-field-error-anchor'; const ignoreInputSelector = '.gl-field-error-ignore'; -class GlFieldError { +export default class GlFieldError { constructor({ input, formErrors }) { this.inputElement = $(input); this.inputDomElement = this.inputElement.get(0); @@ -159,6 +159,3 @@ class GlFieldError { this.fieldErrorElement.hide(); } } - -window.gl = window.gl || {}; -window.gl.GlFieldError = GlFieldError; diff --git a/app/assets/javascripts/gl_field_errors.js b/app/assets/javascripts/gl_field_errors.js index 4bef60264bb832b1aadb77057c1b661752788bb4..cf2e6d266086618a2fc8bbcb874a9f4bdd3de995 100644 --- a/app/assets/javascripts/gl_field_errors.js +++ b/app/assets/javascripts/gl_field_errors.js @@ -1,37 +1,35 @@ -/* eslint-disable comma-dangle, class-methods-use-this, max-len, space-before-function-paren, arrow-parens, no-param-reassign */ - -import './gl_field_error'; +import GlFieldError from './gl_field_error'; const customValidationFlag = 'gl-field-error-ignore'; -class GlFieldErrors { +export default class GlFieldErrors { constructor(form) { this.form = $(form); this.state = { inputs: [], - valid: false + valid: false, }; this.initValidators(); } - initValidators () { + initValidators() { // register selectors here as needed const validateSelectors = [':text', ':password', '[type=email]'] - .map((selector) => `input${selector}`).join(','); + .map(selector => `input${selector}`).join(','); this.state.inputs = this.form.find(validateSelectors).toArray() - .filter((input) => !input.classList.contains(customValidationFlag)) - .map((input) => new window.gl.GlFieldError({ input, formErrors: this })); + .filter(input => !input.classList.contains(customValidationFlag)) + .map(input => new GlFieldError({ input, formErrors: this })); - this.form.on('submit', this.catchInvalidFormSubmit); + this.form.on('submit', GlFieldErrors.catchInvalidFormSubmit); } /* Neccessary to prevent intercept and override invalid form submit * because Safari & iOS quietly allow form submission when form is invalid * and prevents disabling of invalid submit button by application.js */ - catchInvalidFormSubmit (event) { - const $form = $(event.currentTarget); + static catchInvalidFormSubmit(e) { + const $form = $(e.currentTarget); if (!$form.attr('novalidate')) { if (!event.currentTarget.checkValidity()) { @@ -50,11 +48,9 @@ class GlFieldErrors { }); } - focusOnFirstInvalid () { - const firstInvalid = this.state.inputs.filter((input) => !input.inputDomElement.validity.valid)[0]; + focusOnFirstInvalid() { + const firstInvalid = this.state.inputs + .filter(input => !input.inputDomElement.validity.valid)[0]; firstInvalid.inputElement.focus(); } } - -window.gl = window.gl || {}; -window.gl.GlFieldErrors = GlFieldErrors; diff --git a/app/assets/javascripts/gl_form.js b/app/assets/javascripts/gl_form.js index 4e8141b2956e023ab323a3a5a937780fba8ab7c8..48d0c12143ae0ce8ff15767be6562a26b6f650e4 100644 --- a/app/assets/javascripts/gl_form.js +++ b/app/assets/javascripts/gl_form.js @@ -1,104 +1,99 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-new, max-len */ -/* global GitLab */ /* global DropzoneInput */ /* global autosize */ import GfmAutoComplete from './gfm_auto_complete'; -window.gl = window.gl || {}; - -function GLForm(form, enableGFM = false) { - this.form = form; - this.textarea = this.form.find('textarea.js-gfm-input'); - this.enableGFM = enableGFM; - // Before we start, we should clean up any previous data for this form - this.destroy(); - // Setup the form - this.setupForm(); - this.form.data('gl-form', this); -} - -GLForm.prototype.destroy = function() { - // Clean form listeners - this.clearEventListeners(); - if (this.autoComplete) { - this.autoComplete.destroy(); +export default class GLForm { + constructor(form, enableGFM = false) { + this.form = form; + this.textarea = this.form.find('textarea.js-gfm-input'); + this.enableGFM = enableGFM; + // Before we start, we should clean up any previous data for this form + this.destroy(); + // Setup the form + this.setupForm(); + this.form.data('gl-form', this); } - return this.form.data('gl-form', null); -}; -GLForm.prototype.setupForm = function() { - var isNewForm; - isNewForm = this.form.is(':not(.gfm-form)'); - this.form.removeClass('js-new-note-form'); - if (isNewForm) { - this.form.find('.div-dropzone').remove(); - this.form.addClass('gfm-form'); - // remove notify commit author checkbox for non-commit notes - gl.utils.disableButtonIfEmptyField(this.form.find('.js-note-text'), this.form.find('.js-comment-button, .js-note-new-discussion')); - this.autoComplete = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources); - this.autoComplete.setup(this.form.find('.js-gfm-input'), { - emojis: true, - members: this.enableGFM, - issues: this.enableGFM, - milestones: this.enableGFM, - mergeRequests: this.enableGFM, - labels: this.enableGFM, - }); - new DropzoneInput(this.form); - autosize(this.textarea); + destroy() { + // Clean form listeners + this.clearEventListeners(); + if (this.autoComplete) { + this.autoComplete.destroy(); + } + this.form.data('gl-form', null); } - // form and textarea event listeners - this.addEventListeners(); - gl.text.init(this.form); - // hide discard button - this.form.find('.js-note-discard').hide(); - this.form.show(); - if (this.isAutosizeable) this.setupAutosize(); -}; -GLForm.prototype.setupAutosize = function () { - this.textarea.off('autosize:resized') - .on('autosize:resized', this.setHeightData.bind(this)); + setupForm() { + const isNewForm = this.form.is(':not(.gfm-form)'); + this.form.removeClass('js-new-note-form'); + if (isNewForm) { + this.form.find('.div-dropzone').remove(); + this.form.addClass('gfm-form'); + // remove notify commit author checkbox for non-commit notes + gl.utils.disableButtonIfEmptyField(this.form.find('.js-note-text'), this.form.find('.js-comment-button, .js-note-new-discussion')); + this.autoComplete = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources); + this.autoComplete.setup(this.form.find('.js-gfm-input'), { + emojis: true, + members: this.enableGFM, + issues: this.enableGFM, + milestones: this.enableGFM, + mergeRequests: this.enableGFM, + labels: this.enableGFM, + }); + new DropzoneInput(this.form); // eslint-disable-line no-new + autosize(this.textarea); + } + // form and textarea event listeners + this.addEventListeners(); + gl.text.init(this.form); + // hide discard button + this.form.find('.js-note-discard').hide(); + this.form.show(); + if (this.isAutosizeable) this.setupAutosize(); + } - this.textarea.off('mouseup.autosize') - .on('mouseup.autosize', this.destroyAutosize.bind(this)); + setupAutosize() { + this.textarea.off('autosize:resized') + .on('autosize:resized', this.setHeightData.bind(this)); - setTimeout(() => { - autosize(this.textarea); - this.textarea.css('resize', 'vertical'); - }, 0); -}; + this.textarea.off('mouseup.autosize') + .on('mouseup.autosize', this.destroyAutosize.bind(this)); -GLForm.prototype.setHeightData = function () { - this.textarea.data('height', this.textarea.outerHeight()); -}; + setTimeout(() => { + autosize(this.textarea); + this.textarea.css('resize', 'vertical'); + }, 0); + } -GLForm.prototype.destroyAutosize = function () { - const outerHeight = this.textarea.outerHeight(); + setHeightData() { + this.textarea.data('height', this.textarea.outerHeight()); + } - if (this.textarea.data('height') === outerHeight) return; + destroyAutosize() { + const outerHeight = this.textarea.outerHeight(); - autosize.destroy(this.textarea); + if (this.textarea.data('height') === outerHeight) return; - this.textarea.data('height', outerHeight); - this.textarea.outerHeight(outerHeight); - this.textarea.css('max-height', window.outerHeight); -}; + autosize.destroy(this.textarea); -GLForm.prototype.clearEventListeners = function() { - this.textarea.off('focus'); - this.textarea.off('blur'); - return gl.text.removeListeners(this.form); -}; + this.textarea.data('height', outerHeight); + this.textarea.outerHeight(outerHeight); + this.textarea.css('max-height', window.outerHeight); + } -GLForm.prototype.addEventListeners = function() { - this.textarea.on('focus', function() { - return $(this).closest('.md-area').addClass('is-focused'); - }); - return this.textarea.on('blur', function() { - return $(this).closest('.md-area').removeClass('is-focused'); - }); -}; + clearEventListeners() { + this.textarea.off('focus'); + this.textarea.off('blur'); + gl.text.removeListeners(this.form); + } -window.gl.GLForm = GLForm; + addEventListeners() { + this.textarea.on('focus', function focusTextArea() { + $(this).closest('.md-area').addClass('is-focused'); + }); + this.textarea.on('blur', function blurTextArea() { + $(this).closest('.md-area').removeClass('is-focused'); + }); + } +} diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index cf7322ba1da6ead26025e9b1cedae9ae24887352..2934cfe013cccd88b10d1cf1ac55e2df9010e870 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -19,6 +19,7 @@ import 'vendor/jquery.atwho'; import AjaxCache from '~/lib/utils/ajax_cache'; import Flash from './flash'; import CommentTypeToggle from './comment_type_toggle'; +import GLForm from './gl_form'; import loadAwardsHandler from './awards_handler'; import './autosave'; import './dropzone_input'; @@ -557,7 +558,7 @@ export default class Notes { */ setupNoteForm(form) { var textarea, key; - new gl.GLForm(form, this.enableGFM); + new GLForm(form, this.enableGFM); textarea = form.find('.js-note-text'); key = [ 'Note', @@ -1152,7 +1153,7 @@ export default class Notes { var targetId = $originalContentEl.data('target-id'); var targetType = $originalContentEl.data('target-type'); - new gl.GLForm($editForm.find('form'), this.enableGFM); + new GLForm($editForm.find('form'), this.enableGFM); $editForm.find('form') .attr('action', postUrl) diff --git a/app/assets/javascripts/pipeline_schedules/pipeline_schedule_form_bundle.js b/app/assets/javascripts/pipeline_schedules/pipeline_schedule_form_bundle.js index 50c725aa3d54954d5446c976195532b9c9fc075f..f1cf6e92ef51efdf8892c726605f720114d7a803 100644 --- a/app/assets/javascripts/pipeline_schedules/pipeline_schedule_form_bundle.js +++ b/app/assets/javascripts/pipeline_schedules/pipeline_schedule_form_bundle.js @@ -1,5 +1,6 @@ import Vue from 'vue'; import Translate from '../vue_shared/translate'; +import GlFieldErrors from '../gl_field_errors'; import intervalPatternInput from './components/interval_pattern_input.vue'; import TimezoneDropdown from './components/timezone_dropdown'; import TargetBranchDropdown from './components/target_branch_dropdown'; @@ -39,7 +40,7 @@ document.addEventListener('DOMContentLoaded', () => { gl.timezoneDropdown = new TimezoneDropdown(); gl.targetBranchDropdown = new TargetBranchDropdown(); - gl.pipelineScheduleFieldErrors = new gl.GlFieldErrors(formElement); + gl.pipelineScheduleFieldErrors = new GlFieldErrors(formElement); setupPipelineVariableList($('.js-pipeline-variable-list')); }); diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue index af4187fab4642a0c2e9c009da3b30c6586e8d661..8c0d9b9cda8a11fdd330d514cf937c1471009f60 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/field.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue @@ -1,5 +1,6 @@