UNPKG

videomail-client

Version:

A wicked npm package to record videos directly in the browser, wohooo!

312 lines (244 loc) 7.96 kB
import getFormData from 'get-form-data' import hidden from 'hidden' import h from 'hyperscript' import util from 'util' import Events from '../events' import EventEmitter from '../util/eventEmitter' import VideomailError from '../util/videomailError' // fixes https://github.com/binarykitchen/videomail-client/issues/71 function trimEmail(email) { return email.replace(/(^[,\s]+)|([,\s]+$)/g, '') } const Form = function (container, formElement, options) { EventEmitter.call(this, options, 'Form') const self = this let keyInput function getData() { return getFormData(formElement, { includeDisabled: true }) } this.transformFormData = function (formData) { const FORM_FIELDS = { subject: options.selectors.subjectInputName, from: options.selectors.fromInputName, to: options.selectors.toInputName, cc: options.selectors.ccInputName, bcc: options.selectors.bccInputName, body: options.selectors.bodyInputName, key: options.selectors.keyInputName, parentKey: options.selectors.parentKeyInputName, sendCopy: options.selectors.sendCopyInputName } const transformedFormData = {} Object.keys(FORM_FIELDS).forEach(function (key) { const formFieldValue = FORM_FIELDS[key] if (formFieldValue in formData) { transformedFormData[key] = formData[formFieldValue] } }) if (transformedFormData.from) { transformedFormData.from = trimEmail(transformedFormData.from) } if (transformedFormData.to) { transformedFormData.to = trimEmail(transformedFormData.to) } if (transformedFormData.cc) { transformedFormData.cc = trimEmail(transformedFormData.cc) } if (transformedFormData.bcc) { transformedFormData.bcc = trimEmail(transformedFormData.bcc) } return transformedFormData } this.getRecipients = function () { const videomailFormData = this.transformFormData(getData()) const recipients = {} if ('to' in videomailFormData) { recipients.to = videomailFormData.to } if ('cc' in videomailFormData) { recipients.cc = videomailFormData.cc } if ('bcc' in videomailFormData) { recipients.bcc = videomailFormData.bcc } return recipients } this.loadVideomail = function (videomail) { const limit = formElement.elements.length let input let name for (let i = 0; i < limit; i++) { input = formElement.elements[i] name = input.name if (videomail[name]) { input.value = videomail[name] } if ( name === options.selectors.subjectInputName || name === options.selectors.bodyInputName ) { input.disabled = true } } formElement.setAttribute('method', 'put') } function isNotButton(element) { return element.tagName !== 'BUTTON' && element.type !== 'submit' } function setDisabled(disabled, buttonsToo) { const limit = formElement.elements.length for (let i = 0; i < limit; i++) { if (buttonsToo || (!buttonsToo && isNotButton(formElement.elements[i]))) { formElement.elements[i].disabled = disabled } } } function hideAll() { const limit = formElement.elements.length for (let i = 0; i < limit; i++) { hidden(formElement.elements[i], true) } hidden(formElement, true) } function getInputElements() { return formElement.querySelectorAll('input, textarea') } function getSelectElements() { return formElement.querySelectorAll('select') } this.disable = function (buttonsToo) { setDisabled(true, buttonsToo) } this.enable = function (buttonsToo) { setDisabled(false, buttonsToo) } this.build = function () { if (options.enableAutoValidation) { const inputElements = getInputElements() let inputElement for (let i = 0, len = inputElements.length; i < len; i++) { inputElement = inputElements[i] if (inputElement.type === 'radio') { inputElement.addEventListener('change', function () { container.validate() }) } else { inputElement.addEventListener('input', function () { // let angular validate first, e.g. remove the custom error setTimeout(function () { container.validate() }, 0) }) } } const selectElements = getSelectElements() for (let j = 0, len2 = selectElements.length; j < len2; j++) { selectElements[j].addEventListener('change', function () { container.validate() }) } } keyInput = formElement.querySelector( 'input[name="' + options.selectors.keyInputName + '"]' ) if (!keyInput) { keyInput = h('input', { name: options.selectors.keyInputName, type: 'hidden' }) formElement.appendChild(keyInput) } this.on(Events.PREVIEW, function (videomailKey) { // beware that preview doesn't always come with a key, i.E. // container.show() can emit PREVIEW without a key when a replay already exists // (can happen when showing - hiding - showing videomail over again) // only emit error if key is missing AND the input has no key (value) yet if (!videomailKey && !keyInput.value) { self.emit( Events.ERROR, VideomailError.create('Videomail key for preview is missing!', options) ) } else if (videomailKey) { keyInput.value = videomailKey } // else // leave as it and use existing keyInput.value }) // fixes https://github.com/binarykitchen/videomail-client/issues/91 this.on(Events.GOING_BACK, () => { keyInput.value = null }) this.on(Events.ERROR, function (err) { // since https://github.com/binarykitchen/videomail-client/issues/60 // we hide areas to make it easier for the user to process an error // (= less distractions) if (err.hideForm && err.hideForm() && options.adjustFormOnBrowserError) { hideAll() } else if ( err.hideButtons && err.hideButtons() && options.adjustFormOnBrowserError ) { hideSubmitButton() } }) this.on(Events.BUILT, function () { startListeningToSubmitEvents() }) } function hideSubmitButton() { const submitButton = self.findSubmitButton() hidden(submitButton, true) } function startListeningToSubmitEvents() { const submitButton = container.getSubmitButton() submitButton.addEventListener('click', self.doTheSubmit.bind(self)) } this.doTheSubmit = (e) => { if (e) { e.preventDefault() } // only submit when there is a container, // otherwise do nothing and leave as it if (container.hasElement()) { container.submitAll( getData(), formElement.getAttribute('method'), formElement.getAttribute('action') ) } return false // important to stop submission } this.getInvalidElement = () => { const inputElements = getInputElements() let i = 0 for (const len = inputElements.length; i < len; i++) { if (!inputElements[i].validity.valid) { return inputElements[i] } } const selectElements = getSelectElements() let j = 0 for (const len2 = selectElements.length; j < len2; j++) { if (!selectElements[j].validity.valid) { return selectElements[j] } } return null } this.validate = function () { const formIsValid = formElement.checkValidity() return formIsValid } this.findSubmitButton = function () { return formElement.querySelector("[type='submit']") } this.hide = function () { formElement && hidden(formElement, true) } this.show = function () { formElement && hidden(formElement, false) } } util.inherits(Form, EventEmitter) export default Form