Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions src/assets/css/common.css
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ header.vff-header svg.f-logo {
.vff input[type=email],
.vff input[type=url],
.vff input[type=password],
.vff input[type=date],
.vff textarea {
-webkit-appearance: none;
-moz-appearance: none;
Expand Down Expand Up @@ -384,6 +385,7 @@ header.vff-header svg.f-logo {
.vff .f-full-width input[type=email],
.vff .f-full-width input[type=url],
.vff .f-full-width input[type=password],
.vff .f-full-width input[type=date],
.vff .f-full-width textarea,
.vff .f-full-width span.faux-form{
width: 100%;
Expand Down Expand Up @@ -437,6 +439,27 @@ header.vff-header svg.f-logo {
height: auto;
}

/* ios datepicker */
.vff.vff-is-ios .field-datetype:not(.f-has-value) .f-answer > span {
position: relative;
top: 0;
left: 0;
}

.vff.vff-is-ios .field-datetype:not(.f-has-value) .f-answer > span::before {
position: absolute;
content: attr(data-placeholder);
display: block;
pointer-events: none;
padding: 0.12em .2em;
}

.vff.vff-is-ios input[type=date] {
height: 32px;
display: block;
}


/*
links
*/
Expand Down Expand Up @@ -825,6 +848,7 @@ header.vff-header svg.f-logo {
.vff input[type=email],
.vff input[type=url],
.vff input[type=password],
.vff input[type=date],
.vff textarea{
font-size: .78em;
}
Expand Down Expand Up @@ -870,6 +894,7 @@ header.vff-header svg.f-logo {
.vff input[type=email],
.vff input[type=url],
.vff input[type=password],
.vff input[type=date],
.vff textarea {
line-height: 1.4;
padding: .16em .2em;
Expand Down
9 changes: 9 additions & 0 deletions src/assets/css/themes/theme-green.css
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ header.vff-header svg.f-logo {
.vff input[type=email],
.vff input[type=url],
.vff input[type=password],
.vff input[type=date],
.vff textarea,
.vff span.faux-form {
border-bottom-color: var(--vff-secondary-text-color);
Expand Down Expand Up @@ -104,6 +105,14 @@ header.vff-header svg.f-logo {
font-weight: 300;
}


/*faux input type date placeholder for iOS*/
.vff.vff-is-ios .field-datetype:not(.f-has-value) .f-answer > span::before{
color: var(--vff-secondary-text-color);
font-weight: 300;
font-size: .72em;
}

/*field-multiplechoicetype*/
.vff ul.f-radios li {
border: 1px solid var(--vff-secondary-text-color);
Expand Down
8 changes: 8 additions & 0 deletions src/assets/css/themes/theme-minimal.css
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ header.vff-header svg.f-logo{
.vff input[type=email],
.vff input[type=url],
.vff input[type=password],
.vff input[type=date],
.vff textarea,
.vff span.faux-form {
border-bottom-color: var(--vff-secondary-text-color);
Expand Down Expand Up @@ -98,6 +99,13 @@ header.vff-header svg.f-logo{
font-weight: 300;
}

/*faux input type date placeholder for iOS*/
.vff.vff-is-ios .field-datetype:not(.f-has-value) .f-answer > span::before{
color: var(--vff-secondary-text-color);
font-weight: 300;
font-size: .72em;
}

/*field-multiplechoicetype*/
.vff ul.f-radios li {
border: 1px solid var(--vff-secondary-text-color);
Expand Down
8 changes: 8 additions & 0 deletions src/assets/css/themes/theme-purple.css
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ header.vff-header svg.f-logo{
.vff input[type=email],
.vff input[type=url],
.vff input[type=password],
.vff input[type=date],
.vff textarea,
.vff span.faux-form {
border-bottom-color: var(--vff-secondary-text-color);
Expand Down Expand Up @@ -114,6 +115,13 @@ header.vff-header svg.f-logo{
font-weight: 300;
}

/*faux input type date placeholder for iOS*/
.vff.vff-is-ios .field-datetype:not(.f-has-value) .f-answer > span::before{
color: var(--vff-secondary-text-color);
font-weight: 300;
font-size: .72em;
}

/*field-multiplechoicetype*/
.vff ul.f-radios li {
border: 1px solid var(--vff-secondary-form-bg-color);
Expand Down
6 changes: 5 additions & 1 deletion src/components/FlowForm.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Form template and logic

<template>
<div class="vff" :class="{'vff-not-standalone': !standalone}">
<div class="vff" :class="{'vff-not-standalone': !standalone, 'vff-is-mobile': isMobile, 'vff-is-ios': isIos}">
<div class="f-container">
<div class="f-form-wrap">
<flow-form-question
Expand Down Expand Up @@ -126,6 +126,7 @@

import FlowFormQuestion from './Question.vue'
import LanguageModel from '../models/LanguageModel'
import { IsMobile } from '../mixins/IsMobile'

export default {
name: 'FlowForm',
Expand All @@ -147,6 +148,9 @@
default: true
}
},
mixins: [
IsMobile,
],
data() {
return {
completed: false,
Expand Down
27 changes: 17 additions & 10 deletions src/components/Question.vue
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
import FlowFormSectionBreakType from './QuestionTypes/SectionBreakType.vue'
import FlowFormTextType from './QuestionTypes/TextType.vue'
import FlowFormUrlType from './QuestionTypes/UrlType.vue'
import FlowFormDateType from './QuestionTypes/DateType.vue'
import { IsMobile } from '../mixins/IsMobile'


Expand All @@ -121,7 +122,8 @@
FlowFormPhoneType,
FlowFormSectionBreakType,
FlowFormTextType,
FlowFormUrlType
FlowFormUrlType,
FlowFormDateType
},
props: {
question: QuestionModel,
Expand Down Expand Up @@ -239,17 +241,22 @@
}
},
computed: {
mainClasses() {
const classes = {
'q-is-active': this.active,
'q-is-inactive': !this.active,
'f-fade-in-down': this.reverse,
'f-fade-in-up': !this.reverse
}
mainClasses: {
cache: false,
get() {
const classes = {
'q-is-active': this.active,
'q-is-inactive': !this.active,
'f-fade-in-down': this.reverse,
'f-fade-in-up': !this.reverse,
'f-focused': this.$refs.questionComponent && this.$refs.questionComponent.focused,
'f-has-value': this.$refs.questionComponent && this.$refs.questionComponent.hasValue
}

classes['field-' + this.question.type.toLowerCase().substring(8)] = true
classes['field-' + this.question.type.toLowerCase().substring(8)] = true

return classes
return classes
}
},

showHelperText() {
Expand Down
35 changes: 35 additions & 0 deletions src/components/QuestionTypes/DateType.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script>
/*
Copyright (c) 2020 - present, DITDOT Ltd. - MIT Licence
https://github.com/ditdot-dev/vue-flow-form
https://www.ditdot.hr/en
*/

import TextType from './TextType.vue'
import { QuestionType } from '../../models/QuestionModel'
import LanguageModel from '../../models/LanguageModel'

export default {
extends: TextType,
name: QuestionType.Date,
data() {
return {
inputType: 'date',
canReceiveFocus: true
}
},
methods: {
validate() {
if (this.question.min && this.dataValue < this.question.min) {
return false
}

if (this.question.max && this.dataValue > this.question.max) {
return false
}

return !this.question.required || this.hasValue
}
}
}
</script>
11 changes: 10 additions & 1 deletion src/components/QuestionTypes/TextType.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<span>
<span v-bind:data-placeholder="inputType === 'date' ? placeholder : null">
<the-mask
v-if="question.mask"
ref="input"
Expand All @@ -15,6 +15,10 @@
v-on:keyup.native.enter.prevent="onEnter"
v-on:keyup.native.tab.prevent="onEnter"
v-bind:placeholder="placeholder"
v-bind:min="question.min"
v-bind:max="question.max"
v-on:change="onChange"
v-bind:tokens="tokens"
/>
<input
v-else
Expand All @@ -28,6 +32,9 @@
v-on:keyup.tab.prevent="onEnter"
v-on:focus="setFocus"
v-on:blur="unsetFocus"
v-bind:min="question.min"
v-bind:max="question.max"
v-on:change="onChange"
v-bind:placeholder="placeholder"
/>
</span>
Expand All @@ -51,12 +58,14 @@
components: {
TheMask
},

data() {
return {
inputType: 'text',
canReceiveFocus: true
}
},

methods: {
validate() {
if (this.question.mask && this.dataValue.length !== this.question.mask.length) {
Expand Down
5 changes: 3 additions & 2 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Import vue component
import FlowForm from './components/FlowForm.vue'
import QuestionModel, { QuestionType, ChoiceOption, LinkOption } from './models/QuestionModel'
import QuestionModel, { QuestionType, ChoiceOption, LinkOption, MaskPresets } from './models/QuestionModel'
import LanguageModel from './models/LanguageModel'

// IE11 Object.assign polyfill
Expand Down Expand Up @@ -37,5 +37,6 @@ export {
QuestionType,
ChoiceOption,
LinkOption,
LanguageModel
LanguageModel,
MaskPresets
}
4 changes: 3 additions & 1 deletion src/mixins/IsMobile.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
*/

// Simple mobile device/tablet detection
const isMobile = !!(typeof navigator !== 'undefined' && navigator.userAgent.match(/android|iphone|ipad|ipod/i))
const isIos = navigator.userAgent.match(/iphone|ipad|ipod/i) || (navigator.userAgent.indexOf("Mac") !== -1 && "ontouchend" in document)
const isMobile = !!(typeof navigator !== 'undefined' && (isIos || navigator.userAgent.match(/android/i)))

// Mixin that adds an `isMobile` data variable
export const IsMobile = {
data() {
return {
isIos,
isMobile
}
}
Expand Down
17 changes: 15 additions & 2 deletions src/models/QuestionModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// Global data store

export const QuestionType = Object.freeze({
Date: 'FlowFormDateType',
Dropdown: 'FlowFormDropdownType',
Email: 'FlowFormEmailType',
LongText: 'FlowFormLongTextType',
Expand All @@ -25,6 +26,12 @@ export const DropdownOptionBlank = Object.freeze({
disabled: true
})

export const MaskPresets = Object.freeze({
Date: '##/##/####',
DateIso: '####-##-##',
PhoneUs: '(###) ###-####'
})

export class ChoiceOption {
constructor(options) {
this.label = ''
Expand Down Expand Up @@ -84,23 +91,29 @@ export default class QuestionModel {
this.helpText = null
this.helpTextShow = true
this.descriptionLink = []
this.min = null
this.max = null

Object.assign(this, options)

// Sets default mask and placeholder value on PhoneType question
if (this.type === QuestionType.Phone) {
if (!this.mask) {
this.mask = '(###) ###-####'
this.mask = MaskPresets.Phone
}
if (!this.placeholder) {
this.placeholder = this.mask
}
}
}

if (this.type === QuestionType.Url) {
this.mask = null
}

if (this.type === QuestionType.Date && !this.placeholder) {
this.placeholder = 'yyyy-mm-dd'
}

if (this.multiple) {
this.answer = []
}
Expand Down