Adds new date format capability and associated tests
This commit is contained in:
parent
ba24fc21e8
commit
cb9349a6cf
273
dist/formulate.esm.js
vendored
273
dist/formulate.esm.js
vendored
@ -36,10 +36,6 @@ var library = {
|
||||
classification: 'text',
|
||||
component: 'FormulateInputText'
|
||||
},
|
||||
range: {
|
||||
classification: 'text',
|
||||
component: 'FormulateInputText'
|
||||
},
|
||||
search: {
|
||||
classification: 'text',
|
||||
component: 'FormulateInputText'
|
||||
@ -65,6 +61,12 @@ var library = {
|
||||
component: 'FormulateInputText'
|
||||
},
|
||||
|
||||
// === SLIDER INPUTS
|
||||
range: {
|
||||
classification: 'slider',
|
||||
component: 'FormulateInputSlider'
|
||||
},
|
||||
|
||||
// === MULTI LINE TEXT INPUTS
|
||||
textarea: {
|
||||
classification: 'textarea',
|
||||
@ -218,6 +220,33 @@ function parseRule (rule, rules) {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string for use in regular expressions.
|
||||
* @param {string} string
|
||||
*/
|
||||
function escapeRegExp (string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') // $& means the whole matched string
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string format (date) return a regex to match against.
|
||||
* @param {string} format
|
||||
*/
|
||||
function regexForFormat (format) {
|
||||
var escaped = "^" + (escapeRegExp(format)) + "$";
|
||||
var formats = {
|
||||
MM: '(0[1-9]|1[012])',
|
||||
M: '([1-9]|1[012])',
|
||||
DD: '([012][1-9]|3[01])',
|
||||
D: '([012]?[1-9]|3[01])',
|
||||
YYYY: '\\d{4}',
|
||||
YY: '\\d{2}'
|
||||
};
|
||||
return new RegExp(Object.keys(formats).reduce(function (regex, format) {
|
||||
return regex.replace(format, formats[format])
|
||||
}, escaped))
|
||||
}
|
||||
|
||||
/**
|
||||
* Library of rules
|
||||
*/
|
||||
@ -304,10 +333,18 @@ var rules = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: ensures the value is a date according to Date.parse()
|
||||
* Rule: ensures the value is a date according to Date.parse(), or a format
|
||||
* regex.
|
||||
*/
|
||||
date: function (value) {
|
||||
return Promise.resolve(!isNaN(Date.parse(value)))
|
||||
date: function (value, format) {
|
||||
if ( format === void 0 ) format = false;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
if (format && typeof format === 'string') {
|
||||
return regexForFormat(format).test(value)
|
||||
}
|
||||
return !isNaN(Date.parse(value))
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
@ -542,7 +579,11 @@ var en = {
|
||||
*/
|
||||
date: function (ref) {
|
||||
var name = ref.name;
|
||||
var args = ref.args;
|
||||
|
||||
if (Array.isArray(args) && args.length) {
|
||||
return ((sentence(name)) + " is not a valid, please use the format " + (args[0]))
|
||||
}
|
||||
return ((sentence(name)) + " is not a valid date.")
|
||||
},
|
||||
|
||||
@ -562,7 +603,10 @@ var en = {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
return (value + " is not a valid email address.")
|
||||
if (!value) {
|
||||
return 'Please enter a valid email address.'
|
||||
}
|
||||
return ("“" + value + "” is not a valid email address.")
|
||||
},
|
||||
|
||||
/**
|
||||
@ -572,10 +616,10 @@ var en = {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
if (typeof value === 'string') {
|
||||
if (typeof value === 'string' && value) {
|
||||
return ("“" + (sentence(value)) + "” is not an allowed " + name + ".")
|
||||
}
|
||||
return ((sentence(name)) + " is not an allowed value.")
|
||||
return ("This is not an allowed " + name + ".")
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1620,7 +1664,8 @@ var __vue_render__$4 = function() {
|
||||
return _c(
|
||||
"div",
|
||||
{
|
||||
staticClass: "formulate-input-element formulate-input-element--box",
|
||||
class:
|
||||
"formulate-input-element formulate-input-element--" + _vm.context.type,
|
||||
attrs: { "data-type": _vm.context.type }
|
||||
},
|
||||
[
|
||||
@ -1795,7 +1840,9 @@ var __vue_render__$5 = function() {
|
||||
return _c(
|
||||
"div",
|
||||
{
|
||||
staticClass: "formulate-input-element formulate-input-element--textarea"
|
||||
class:
|
||||
"formulate-input-element formulate-input-element--" + _vm.context.type,
|
||||
attrs: { "data-type": _vm.context.type }
|
||||
},
|
||||
[
|
||||
_vm.type === "checkbox"
|
||||
@ -1967,7 +2014,11 @@ var __vue_render__$6 = function() {
|
||||
var _c = _vm._self._c || _h;
|
||||
return _c(
|
||||
"div",
|
||||
{ staticClass: "formulate-input-element formulate-input-element--select" },
|
||||
{
|
||||
class:
|
||||
"formulate-input-element formulate-input-element--" + _vm.context.type,
|
||||
attrs: { "data-type": _vm.context.type }
|
||||
},
|
||||
[
|
||||
_c(
|
||||
"select",
|
||||
@ -2104,7 +2155,7 @@ __vue_render__$6._withStripped = true;
|
||||
//
|
||||
|
||||
var script$7 = {
|
||||
name: 'FormulateInputTextArea',
|
||||
name: 'FormulateInputText',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
@ -2119,7 +2170,172 @@ var __vue_render__$7 = function() {
|
||||
return _c(
|
||||
"div",
|
||||
{
|
||||
staticClass: "formulate-input-element formulate-input-element--textarea"
|
||||
class:
|
||||
"formulate-input-element formulate-input-element--" + _vm.context.type,
|
||||
attrs: { "data-type": _vm.context.type }
|
||||
},
|
||||
[
|
||||
_vm.type === "checkbox"
|
||||
? _c(
|
||||
"input",
|
||||
_vm._b(
|
||||
{
|
||||
directives: [
|
||||
{
|
||||
name: "model",
|
||||
rawName: "v-model",
|
||||
value: _vm.context.model,
|
||||
expression: "context.model"
|
||||
}
|
||||
],
|
||||
attrs: { type: "checkbox" },
|
||||
domProps: {
|
||||
checked: Array.isArray(_vm.context.model)
|
||||
? _vm._i(_vm.context.model, null) > -1
|
||||
: _vm.context.model
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
var $$a = _vm.context.model,
|
||||
$$el = $event.target,
|
||||
$$c = $$el.checked ? true : false;
|
||||
if (Array.isArray($$a)) {
|
||||
var $$v = null,
|
||||
$$i = _vm._i($$a, $$v);
|
||||
if ($$el.checked) {
|
||||
$$i < 0 &&
|
||||
_vm.$set(_vm.context, "model", $$a.concat([$$v]));
|
||||
} else {
|
||||
$$i > -1 &&
|
||||
_vm.$set(
|
||||
_vm.context,
|
||||
"model",
|
||||
$$a.slice(0, $$i).concat($$a.slice($$i + 1))
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_vm.$set(_vm.context, "model", $$c);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"input",
|
||||
_vm.attributes,
|
||||
false
|
||||
)
|
||||
)
|
||||
: _vm.type === "radio"
|
||||
? _c(
|
||||
"input",
|
||||
_vm._b(
|
||||
{
|
||||
directives: [
|
||||
{
|
||||
name: "model",
|
||||
rawName: "v-model",
|
||||
value: _vm.context.model,
|
||||
expression: "context.model"
|
||||
}
|
||||
],
|
||||
attrs: { type: "radio" },
|
||||
domProps: { checked: _vm._q(_vm.context.model, null) },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
return _vm.$set(_vm.context, "model", null)
|
||||
}
|
||||
}
|
||||
},
|
||||
"input",
|
||||
_vm.attributes,
|
||||
false
|
||||
)
|
||||
)
|
||||
: _c(
|
||||
"input",
|
||||
_vm._b(
|
||||
{
|
||||
directives: [
|
||||
{
|
||||
name: "model",
|
||||
rawName: "v-model",
|
||||
value: _vm.context.model,
|
||||
expression: "context.model"
|
||||
}
|
||||
],
|
||||
attrs: { type: _vm.type },
|
||||
domProps: { value: _vm.context.model },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
input: function($event) {
|
||||
if ($event.target.composing) {
|
||||
return
|
||||
}
|
||||
_vm.$set(_vm.context, "model", $event.target.value);
|
||||
}
|
||||
}
|
||||
},
|
||||
"input",
|
||||
_vm.attributes,
|
||||
false
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$7 = [];
|
||||
__vue_render__$7._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$7 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$7 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$7 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$7 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
|
||||
/* style inject shadow dom */
|
||||
|
||||
|
||||
|
||||
var FormulateInputSlider = normalizeComponent(
|
||||
{ render: __vue_render__$7, staticRenderFns: __vue_staticRenderFns__$7 },
|
||||
__vue_inject_styles__$7,
|
||||
__vue_script__$7,
|
||||
__vue_scope_id__$7,
|
||||
__vue_is_functional_template__$7,
|
||||
__vue_module_identifier__$7,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
|
||||
//
|
||||
|
||||
var script$8 = {
|
||||
name: 'FormulateInputTextArea',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$8 = script$8;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$8 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
return _c(
|
||||
"div",
|
||||
{
|
||||
staticClass: "formulate-input-element formulate-input-element--textarea",
|
||||
attrs: { "data-type": "textarea" }
|
||||
},
|
||||
[
|
||||
_c(
|
||||
@ -2153,17 +2369,17 @@ var __vue_render__$7 = function() {
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$7 = [];
|
||||
__vue_render__$7._withStripped = true;
|
||||
var __vue_staticRenderFns__$8 = [];
|
||||
__vue_render__$8._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$7 = undefined;
|
||||
var __vue_inject_styles__$8 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$7 = undefined;
|
||||
var __vue_scope_id__$8 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$7 = undefined;
|
||||
var __vue_module_identifier__$8 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$7 = false;
|
||||
var __vue_is_functional_template__$8 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -2173,12 +2389,12 @@ __vue_render__$7._withStripped = true;
|
||||
|
||||
|
||||
var FormulateInputTextArea = normalizeComponent(
|
||||
{ render: __vue_render__$7, staticRenderFns: __vue_staticRenderFns__$7 },
|
||||
__vue_inject_styles__$7,
|
||||
__vue_script__$7,
|
||||
__vue_scope_id__$7,
|
||||
__vue_is_functional_template__$7,
|
||||
__vue_module_identifier__$7,
|
||||
{ render: __vue_render__$8, staticRenderFns: __vue_staticRenderFns__$8 },
|
||||
__vue_inject_styles__$8,
|
||||
__vue_script__$8,
|
||||
__vue_scope_id__$8,
|
||||
__vue_is_functional_template__$8,
|
||||
__vue_module_identifier__$8,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -2198,6 +2414,7 @@ var Formulate = function Formulate () {
|
||||
FormulateInputText: FormulateInputText,
|
||||
FormulateInputGroup: FormulateInputGroup,
|
||||
FormulateInputSelect: FormulateInputSelect,
|
||||
FormulateInputSlider: FormulateInputSlider,
|
||||
FormulateInputTextArea: FormulateInputTextArea
|
||||
},
|
||||
library: library,
|
||||
@ -2282,6 +2499,8 @@ Formulate.prototype.validationMessage = function validationMessage (rule, valida
|
||||
var generators = this.options.locales[this.options.locale];
|
||||
if (generators.hasOwnProperty(rule)) {
|
||||
return generators[rule](validationContext)
|
||||
} else if (rule[0] === '_' && generators.hasOwnProperty(rule.substr(1))) {
|
||||
return generators[rule.substr(1)](validationContext)
|
||||
}
|
||||
if (generators.hasOwnProperty('default')) {
|
||||
return generators.default(validationContext)
|
||||
|
273
dist/formulate.min.js
vendored
273
dist/formulate.min.js
vendored
@ -39,10 +39,6 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
classification: 'text',
|
||||
component: 'FormulateInputText'
|
||||
},
|
||||
range: {
|
||||
classification: 'text',
|
||||
component: 'FormulateInputText'
|
||||
},
|
||||
search: {
|
||||
classification: 'text',
|
||||
component: 'FormulateInputText'
|
||||
@ -68,6 +64,12 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
component: 'FormulateInputText'
|
||||
},
|
||||
|
||||
// === SLIDER INPUTS
|
||||
range: {
|
||||
classification: 'slider',
|
||||
component: 'FormulateInputSlider'
|
||||
},
|
||||
|
||||
// === MULTI LINE TEXT INPUTS
|
||||
textarea: {
|
||||
classification: 'textarea',
|
||||
@ -221,6 +223,33 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string for use in regular expressions.
|
||||
* @param {string} string
|
||||
*/
|
||||
function escapeRegExp (string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') // $& means the whole matched string
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string format (date) return a regex to match against.
|
||||
* @param {string} format
|
||||
*/
|
||||
function regexForFormat (format) {
|
||||
var escaped = "^" + (escapeRegExp(format)) + "$";
|
||||
var formats = {
|
||||
MM: '(0[1-9]|1[012])',
|
||||
M: '([1-9]|1[012])',
|
||||
DD: '([012][1-9]|3[01])',
|
||||
D: '([012]?[1-9]|3[01])',
|
||||
YYYY: '\\d{4}',
|
||||
YY: '\\d{2}'
|
||||
};
|
||||
return new RegExp(Object.keys(formats).reduce(function (regex, format) {
|
||||
return regex.replace(format, formats[format])
|
||||
}, escaped))
|
||||
}
|
||||
|
||||
/**
|
||||
* Library of rules
|
||||
*/
|
||||
@ -307,10 +336,18 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: ensures the value is a date according to Date.parse()
|
||||
* Rule: ensures the value is a date according to Date.parse(), or a format
|
||||
* regex.
|
||||
*/
|
||||
date: function (value) {
|
||||
return Promise.resolve(!isNaN(Date.parse(value)))
|
||||
date: function (value, format) {
|
||||
if ( format === void 0 ) format = false;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
if (format && typeof format === 'string') {
|
||||
return regexForFormat(format).test(value)
|
||||
}
|
||||
return !isNaN(Date.parse(value))
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
@ -545,7 +582,11 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
*/
|
||||
date: function (ref) {
|
||||
var name = ref.name;
|
||||
var args = ref.args;
|
||||
|
||||
if (Array.isArray(args) && args.length) {
|
||||
return ((sentence(name)) + " is not a valid, please use the format " + (args[0]))
|
||||
}
|
||||
return ((sentence(name)) + " is not a valid date.")
|
||||
},
|
||||
|
||||
@ -565,7 +606,10 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
return (value + " is not a valid email address.")
|
||||
if (!value) {
|
||||
return 'Please enter a valid email address.'
|
||||
}
|
||||
return ("“" + value + "” is not a valid email address.")
|
||||
},
|
||||
|
||||
/**
|
||||
@ -575,10 +619,10 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
if (typeof value === 'string') {
|
||||
if (typeof value === 'string' && value) {
|
||||
return ("“" + (sentence(value)) + "” is not an allowed " + name + ".")
|
||||
}
|
||||
return ((sentence(name)) + " is not an allowed value.")
|
||||
return ("This is not an allowed " + name + ".")
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1623,7 +1667,8 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
return _c(
|
||||
"div",
|
||||
{
|
||||
staticClass: "formulate-input-element formulate-input-element--box",
|
||||
class:
|
||||
"formulate-input-element formulate-input-element--" + _vm.context.type,
|
||||
attrs: { "data-type": _vm.context.type }
|
||||
},
|
||||
[
|
||||
@ -1798,7 +1843,9 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
return _c(
|
||||
"div",
|
||||
{
|
||||
staticClass: "formulate-input-element formulate-input-element--textarea"
|
||||
class:
|
||||
"formulate-input-element formulate-input-element--" + _vm.context.type,
|
||||
attrs: { "data-type": _vm.context.type }
|
||||
},
|
||||
[
|
||||
_vm.type === "checkbox"
|
||||
@ -1970,7 +2017,11 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
var _c = _vm._self._c || _h;
|
||||
return _c(
|
||||
"div",
|
||||
{ staticClass: "formulate-input-element formulate-input-element--select" },
|
||||
{
|
||||
class:
|
||||
"formulate-input-element formulate-input-element--" + _vm.context.type,
|
||||
attrs: { "data-type": _vm.context.type }
|
||||
},
|
||||
[
|
||||
_c(
|
||||
"select",
|
||||
@ -2107,7 +2158,7 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
//
|
||||
|
||||
var script$7 = {
|
||||
name: 'FormulateInputTextArea',
|
||||
name: 'FormulateInputText',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
@ -2122,7 +2173,172 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
return _c(
|
||||
"div",
|
||||
{
|
||||
staticClass: "formulate-input-element formulate-input-element--textarea"
|
||||
class:
|
||||
"formulate-input-element formulate-input-element--" + _vm.context.type,
|
||||
attrs: { "data-type": _vm.context.type }
|
||||
},
|
||||
[
|
||||
_vm.type === "checkbox"
|
||||
? _c(
|
||||
"input",
|
||||
_vm._b(
|
||||
{
|
||||
directives: [
|
||||
{
|
||||
name: "model",
|
||||
rawName: "v-model",
|
||||
value: _vm.context.model,
|
||||
expression: "context.model"
|
||||
}
|
||||
],
|
||||
attrs: { type: "checkbox" },
|
||||
domProps: {
|
||||
checked: Array.isArray(_vm.context.model)
|
||||
? _vm._i(_vm.context.model, null) > -1
|
||||
: _vm.context.model
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
var $$a = _vm.context.model,
|
||||
$$el = $event.target,
|
||||
$$c = $$el.checked ? true : false;
|
||||
if (Array.isArray($$a)) {
|
||||
var $$v = null,
|
||||
$$i = _vm._i($$a, $$v);
|
||||
if ($$el.checked) {
|
||||
$$i < 0 &&
|
||||
_vm.$set(_vm.context, "model", $$a.concat([$$v]));
|
||||
} else {
|
||||
$$i > -1 &&
|
||||
_vm.$set(
|
||||
_vm.context,
|
||||
"model",
|
||||
$$a.slice(0, $$i).concat($$a.slice($$i + 1))
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_vm.$set(_vm.context, "model", $$c);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"input",
|
||||
_vm.attributes,
|
||||
false
|
||||
)
|
||||
)
|
||||
: _vm.type === "radio"
|
||||
? _c(
|
||||
"input",
|
||||
_vm._b(
|
||||
{
|
||||
directives: [
|
||||
{
|
||||
name: "model",
|
||||
rawName: "v-model",
|
||||
value: _vm.context.model,
|
||||
expression: "context.model"
|
||||
}
|
||||
],
|
||||
attrs: { type: "radio" },
|
||||
domProps: { checked: _vm._q(_vm.context.model, null) },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
return _vm.$set(_vm.context, "model", null)
|
||||
}
|
||||
}
|
||||
},
|
||||
"input",
|
||||
_vm.attributes,
|
||||
false
|
||||
)
|
||||
)
|
||||
: _c(
|
||||
"input",
|
||||
_vm._b(
|
||||
{
|
||||
directives: [
|
||||
{
|
||||
name: "model",
|
||||
rawName: "v-model",
|
||||
value: _vm.context.model,
|
||||
expression: "context.model"
|
||||
}
|
||||
],
|
||||
attrs: { type: _vm.type },
|
||||
domProps: { value: _vm.context.model },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
input: function($event) {
|
||||
if ($event.target.composing) {
|
||||
return
|
||||
}
|
||||
_vm.$set(_vm.context, "model", $event.target.value);
|
||||
}
|
||||
}
|
||||
},
|
||||
"input",
|
||||
_vm.attributes,
|
||||
false
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$7 = [];
|
||||
__vue_render__$7._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$7 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$7 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$7 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$7 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
|
||||
/* style inject shadow dom */
|
||||
|
||||
|
||||
|
||||
var FormulateInputSlider = normalizeComponent(
|
||||
{ render: __vue_render__$7, staticRenderFns: __vue_staticRenderFns__$7 },
|
||||
__vue_inject_styles__$7,
|
||||
__vue_script__$7,
|
||||
__vue_scope_id__$7,
|
||||
__vue_is_functional_template__$7,
|
||||
__vue_module_identifier__$7,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
|
||||
//
|
||||
|
||||
var script$8 = {
|
||||
name: 'FormulateInputTextArea',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$8 = script$8;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$8 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
return _c(
|
||||
"div",
|
||||
{
|
||||
staticClass: "formulate-input-element formulate-input-element--textarea",
|
||||
attrs: { "data-type": "textarea" }
|
||||
},
|
||||
[
|
||||
_c(
|
||||
@ -2156,17 +2372,17 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$7 = [];
|
||||
__vue_render__$7._withStripped = true;
|
||||
var __vue_staticRenderFns__$8 = [];
|
||||
__vue_render__$8._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$7 = undefined;
|
||||
var __vue_inject_styles__$8 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$7 = undefined;
|
||||
var __vue_scope_id__$8 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$7 = undefined;
|
||||
var __vue_module_identifier__$8 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$7 = false;
|
||||
var __vue_is_functional_template__$8 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -2176,12 +2392,12 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
|
||||
|
||||
var FormulateInputTextArea = normalizeComponent(
|
||||
{ render: __vue_render__$7, staticRenderFns: __vue_staticRenderFns__$7 },
|
||||
__vue_inject_styles__$7,
|
||||
__vue_script__$7,
|
||||
__vue_scope_id__$7,
|
||||
__vue_is_functional_template__$7,
|
||||
__vue_module_identifier__$7,
|
||||
{ render: __vue_render__$8, staticRenderFns: __vue_staticRenderFns__$8 },
|
||||
__vue_inject_styles__$8,
|
||||
__vue_script__$8,
|
||||
__vue_scope_id__$8,
|
||||
__vue_is_functional_template__$8,
|
||||
__vue_module_identifier__$8,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -2201,6 +2417,7 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
FormulateInputText: FormulateInputText,
|
||||
FormulateInputGroup: FormulateInputGroup,
|
||||
FormulateInputSelect: FormulateInputSelect,
|
||||
FormulateInputSlider: FormulateInputSlider,
|
||||
FormulateInputTextArea: FormulateInputTextArea
|
||||
},
|
||||
library: library,
|
||||
@ -2285,6 +2502,8 @@ var Formulate = (function (exports, isUrl, isPlainObject, nanoid) {
|
||||
var generators = this.options.locales[this.options.locale];
|
||||
if (generators.hasOwnProperty(rule)) {
|
||||
return generators[rule](validationContext)
|
||||
} else if (rule[0] === '_' && generators.hasOwnProperty(rule.substr(1))) {
|
||||
return generators[rule.substr(1)](validationContext)
|
||||
}
|
||||
if (generators.hasOwnProperty('default')) {
|
||||
return generators.default(validationContext)
|
||||
|
273
dist/formulate.umd.js
vendored
273
dist/formulate.umd.js
vendored
@ -42,10 +42,6 @@
|
||||
classification: 'text',
|
||||
component: 'FormulateInputText'
|
||||
},
|
||||
range: {
|
||||
classification: 'text',
|
||||
component: 'FormulateInputText'
|
||||
},
|
||||
search: {
|
||||
classification: 'text',
|
||||
component: 'FormulateInputText'
|
||||
@ -71,6 +67,12 @@
|
||||
component: 'FormulateInputText'
|
||||
},
|
||||
|
||||
// === SLIDER INPUTS
|
||||
range: {
|
||||
classification: 'slider',
|
||||
component: 'FormulateInputSlider'
|
||||
},
|
||||
|
||||
// === MULTI LINE TEXT INPUTS
|
||||
textarea: {
|
||||
classification: 'textarea',
|
||||
@ -224,6 +226,33 @@
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string for use in regular expressions.
|
||||
* @param {string} string
|
||||
*/
|
||||
function escapeRegExp (string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') // $& means the whole matched string
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string format (date) return a regex to match against.
|
||||
* @param {string} format
|
||||
*/
|
||||
function regexForFormat (format) {
|
||||
var escaped = "^" + (escapeRegExp(format)) + "$";
|
||||
var formats = {
|
||||
MM: '(0[1-9]|1[012])',
|
||||
M: '([1-9]|1[012])',
|
||||
DD: '([012][1-9]|3[01])',
|
||||
D: '([012]?[1-9]|3[01])',
|
||||
YYYY: '\\d{4}',
|
||||
YY: '\\d{2}'
|
||||
};
|
||||
return new RegExp(Object.keys(formats).reduce(function (regex, format) {
|
||||
return regex.replace(format, formats[format])
|
||||
}, escaped))
|
||||
}
|
||||
|
||||
/**
|
||||
* Library of rules
|
||||
*/
|
||||
@ -310,10 +339,18 @@
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: ensures the value is a date according to Date.parse()
|
||||
* Rule: ensures the value is a date according to Date.parse(), or a format
|
||||
* regex.
|
||||
*/
|
||||
date: function (value) {
|
||||
return Promise.resolve(!isNaN(Date.parse(value)))
|
||||
date: function (value, format) {
|
||||
if ( format === void 0 ) format = false;
|
||||
|
||||
return Promise.resolve((function () {
|
||||
if (format && typeof format === 'string') {
|
||||
return regexForFormat(format).test(value)
|
||||
}
|
||||
return !isNaN(Date.parse(value))
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
@ -548,7 +585,11 @@
|
||||
*/
|
||||
date: function (ref) {
|
||||
var name = ref.name;
|
||||
var args = ref.args;
|
||||
|
||||
if (Array.isArray(args) && args.length) {
|
||||
return ((sentence(name)) + " is not a valid, please use the format " + (args[0]))
|
||||
}
|
||||
return ((sentence(name)) + " is not a valid date.")
|
||||
},
|
||||
|
||||
@ -568,7 +609,10 @@
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
return (value + " is not a valid email address.")
|
||||
if (!value) {
|
||||
return 'Please enter a valid email address.'
|
||||
}
|
||||
return ("“" + value + "” is not a valid email address.")
|
||||
},
|
||||
|
||||
/**
|
||||
@ -578,10 +622,10 @@
|
||||
var name = ref.name;
|
||||
var value = ref.value;
|
||||
|
||||
if (typeof value === 'string') {
|
||||
if (typeof value === 'string' && value) {
|
||||
return ("“" + (sentence(value)) + "” is not an allowed " + name + ".")
|
||||
}
|
||||
return ((sentence(name)) + " is not an allowed value.")
|
||||
return ("This is not an allowed " + name + ".")
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1626,7 +1670,8 @@
|
||||
return _c(
|
||||
"div",
|
||||
{
|
||||
staticClass: "formulate-input-element formulate-input-element--box",
|
||||
class:
|
||||
"formulate-input-element formulate-input-element--" + _vm.context.type,
|
||||
attrs: { "data-type": _vm.context.type }
|
||||
},
|
||||
[
|
||||
@ -1801,7 +1846,9 @@
|
||||
return _c(
|
||||
"div",
|
||||
{
|
||||
staticClass: "formulate-input-element formulate-input-element--textarea"
|
||||
class:
|
||||
"formulate-input-element formulate-input-element--" + _vm.context.type,
|
||||
attrs: { "data-type": _vm.context.type }
|
||||
},
|
||||
[
|
||||
_vm.type === "checkbox"
|
||||
@ -1973,7 +2020,11 @@
|
||||
var _c = _vm._self._c || _h;
|
||||
return _c(
|
||||
"div",
|
||||
{ staticClass: "formulate-input-element formulate-input-element--select" },
|
||||
{
|
||||
class:
|
||||
"formulate-input-element formulate-input-element--" + _vm.context.type,
|
||||
attrs: { "data-type": _vm.context.type }
|
||||
},
|
||||
[
|
||||
_c(
|
||||
"select",
|
||||
@ -2110,7 +2161,7 @@
|
||||
//
|
||||
|
||||
var script$7 = {
|
||||
name: 'FormulateInputTextArea',
|
||||
name: 'FormulateInputText',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
@ -2125,7 +2176,172 @@
|
||||
return _c(
|
||||
"div",
|
||||
{
|
||||
staticClass: "formulate-input-element formulate-input-element--textarea"
|
||||
class:
|
||||
"formulate-input-element formulate-input-element--" + _vm.context.type,
|
||||
attrs: { "data-type": _vm.context.type }
|
||||
},
|
||||
[
|
||||
_vm.type === "checkbox"
|
||||
? _c(
|
||||
"input",
|
||||
_vm._b(
|
||||
{
|
||||
directives: [
|
||||
{
|
||||
name: "model",
|
||||
rawName: "v-model",
|
||||
value: _vm.context.model,
|
||||
expression: "context.model"
|
||||
}
|
||||
],
|
||||
attrs: { type: "checkbox" },
|
||||
domProps: {
|
||||
checked: Array.isArray(_vm.context.model)
|
||||
? _vm._i(_vm.context.model, null) > -1
|
||||
: _vm.context.model
|
||||
},
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
var $$a = _vm.context.model,
|
||||
$$el = $event.target,
|
||||
$$c = $$el.checked ? true : false;
|
||||
if (Array.isArray($$a)) {
|
||||
var $$v = null,
|
||||
$$i = _vm._i($$a, $$v);
|
||||
if ($$el.checked) {
|
||||
$$i < 0 &&
|
||||
_vm.$set(_vm.context, "model", $$a.concat([$$v]));
|
||||
} else {
|
||||
$$i > -1 &&
|
||||
_vm.$set(
|
||||
_vm.context,
|
||||
"model",
|
||||
$$a.slice(0, $$i).concat($$a.slice($$i + 1))
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_vm.$set(_vm.context, "model", $$c);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"input",
|
||||
_vm.attributes,
|
||||
false
|
||||
)
|
||||
)
|
||||
: _vm.type === "radio"
|
||||
? _c(
|
||||
"input",
|
||||
_vm._b(
|
||||
{
|
||||
directives: [
|
||||
{
|
||||
name: "model",
|
||||
rawName: "v-model",
|
||||
value: _vm.context.model,
|
||||
expression: "context.model"
|
||||
}
|
||||
],
|
||||
attrs: { type: "radio" },
|
||||
domProps: { checked: _vm._q(_vm.context.model, null) },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
change: function($event) {
|
||||
return _vm.$set(_vm.context, "model", null)
|
||||
}
|
||||
}
|
||||
},
|
||||
"input",
|
||||
_vm.attributes,
|
||||
false
|
||||
)
|
||||
)
|
||||
: _c(
|
||||
"input",
|
||||
_vm._b(
|
||||
{
|
||||
directives: [
|
||||
{
|
||||
name: "model",
|
||||
rawName: "v-model",
|
||||
value: _vm.context.model,
|
||||
expression: "context.model"
|
||||
}
|
||||
],
|
||||
attrs: { type: _vm.type },
|
||||
domProps: { value: _vm.context.model },
|
||||
on: {
|
||||
blur: _vm.context.blurHandler,
|
||||
input: function($event) {
|
||||
if ($event.target.composing) {
|
||||
return
|
||||
}
|
||||
_vm.$set(_vm.context, "model", $event.target.value);
|
||||
}
|
||||
}
|
||||
},
|
||||
"input",
|
||||
_vm.attributes,
|
||||
false
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$7 = [];
|
||||
__vue_render__$7._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$7 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$7 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$7 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$7 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
|
||||
/* style inject shadow dom */
|
||||
|
||||
|
||||
|
||||
var FormulateInputSlider = normalizeComponent(
|
||||
{ render: __vue_render__$7, staticRenderFns: __vue_staticRenderFns__$7 },
|
||||
__vue_inject_styles__$7,
|
||||
__vue_script__$7,
|
||||
__vue_scope_id__$7,
|
||||
__vue_is_functional_template__$7,
|
||||
__vue_module_identifier__$7,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined
|
||||
);
|
||||
|
||||
//
|
||||
|
||||
var script$8 = {
|
||||
name: 'FormulateInputTextArea',
|
||||
mixins: [FormulateInputMixin]
|
||||
};
|
||||
|
||||
/* script */
|
||||
var __vue_script__$8 = script$8;
|
||||
|
||||
/* template */
|
||||
var __vue_render__$8 = function() {
|
||||
var _vm = this;
|
||||
var _h = _vm.$createElement;
|
||||
var _c = _vm._self._c || _h;
|
||||
return _c(
|
||||
"div",
|
||||
{
|
||||
staticClass: "formulate-input-element formulate-input-element--textarea",
|
||||
attrs: { "data-type": "textarea" }
|
||||
},
|
||||
[
|
||||
_c(
|
||||
@ -2159,17 +2375,17 @@
|
||||
]
|
||||
)
|
||||
};
|
||||
var __vue_staticRenderFns__$7 = [];
|
||||
__vue_render__$7._withStripped = true;
|
||||
var __vue_staticRenderFns__$8 = [];
|
||||
__vue_render__$8._withStripped = true;
|
||||
|
||||
/* style */
|
||||
var __vue_inject_styles__$7 = undefined;
|
||||
var __vue_inject_styles__$8 = undefined;
|
||||
/* scoped */
|
||||
var __vue_scope_id__$7 = undefined;
|
||||
var __vue_scope_id__$8 = undefined;
|
||||
/* module identifier */
|
||||
var __vue_module_identifier__$7 = undefined;
|
||||
var __vue_module_identifier__$8 = undefined;
|
||||
/* functional template */
|
||||
var __vue_is_functional_template__$7 = false;
|
||||
var __vue_is_functional_template__$8 = false;
|
||||
/* style inject */
|
||||
|
||||
/* style inject SSR */
|
||||
@ -2179,12 +2395,12 @@
|
||||
|
||||
|
||||
var FormulateInputTextArea = normalizeComponent(
|
||||
{ render: __vue_render__$7, staticRenderFns: __vue_staticRenderFns__$7 },
|
||||
__vue_inject_styles__$7,
|
||||
__vue_script__$7,
|
||||
__vue_scope_id__$7,
|
||||
__vue_is_functional_template__$7,
|
||||
__vue_module_identifier__$7,
|
||||
{ render: __vue_render__$8, staticRenderFns: __vue_staticRenderFns__$8 },
|
||||
__vue_inject_styles__$8,
|
||||
__vue_script__$8,
|
||||
__vue_scope_id__$8,
|
||||
__vue_is_functional_template__$8,
|
||||
__vue_module_identifier__$8,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
@ -2204,6 +2420,7 @@
|
||||
FormulateInputText: FormulateInputText,
|
||||
FormulateInputGroup: FormulateInputGroup,
|
||||
FormulateInputSelect: FormulateInputSelect,
|
||||
FormulateInputSlider: FormulateInputSlider,
|
||||
FormulateInputTextArea: FormulateInputTextArea
|
||||
},
|
||||
library: library,
|
||||
@ -2288,6 +2505,8 @@
|
||||
var generators = this.options.locales[this.options.locale];
|
||||
if (generators.hasOwnProperty(rule)) {
|
||||
return generators[rule](validationContext)
|
||||
} else if (rule[0] === '_' && generators.hasOwnProperty(rule.substr(1))) {
|
||||
return generators[rule.substr(1)](validationContext)
|
||||
}
|
||||
if (generators.hasOwnProperty('default')) {
|
||||
return generators.default(validationContext)
|
||||
|
39
dist/snow.css
vendored
39
dist/snow.css
vendored
@ -46,6 +46,45 @@
|
||||
.formulate-input[data-classification='text'] input:focus {
|
||||
outline: 0;
|
||||
border: 1px solid #41b883; }
|
||||
.formulate-input[data-classification='slider'] input {
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
font-size: 1em;
|
||||
padding: .5em 0; }
|
||||
.formulate-input[data-classification='slider'] input:focus {
|
||||
outline: 0; }
|
||||
.formulate-input[data-classification='slider'] input::-webkit-slider-thumb {
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border-radius: 1em;
|
||||
background-color: #41b883;
|
||||
margin-top: calc(-.5em + 2px); }
|
||||
.formulate-input[data-classification='slider'] input::-moz-range-thumb {
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border-radius: 1em;
|
||||
background-color: #41b883;
|
||||
margin-top: calc(-.5em + 2px); }
|
||||
.formulate-input[data-classification='slider'] input::-ms-thumb {
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border-radius: 1em;
|
||||
background-color: #41b883;
|
||||
margin-top: calc(-.5em + 2px); }
|
||||
.formulate-input[data-classification='slider'] input::-webkit-slider-runnable-track {
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background-color: #efefef;
|
||||
border-radius: 3px;
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
.formulate-input[data-classification='textarea'] textarea {
|
||||
appearance: none;
|
||||
border-radius: .3em;
|
||||
|
4
dist/snow.min.css
vendored
4
dist/snow.min.css
vendored
File diff suppressed because one or more lines are too long
@ -9,6 +9,7 @@ import FormulateInputGroup from './FormulateInputGroup.vue'
|
||||
import FormulateInputBox from './inputs/FormulateInputBox.vue'
|
||||
import FormulateInputText from './inputs/FormulateInputText.vue'
|
||||
import FormulateInputSelect from './inputs/FormulateInputSelect.vue'
|
||||
import FormulateInputSlider from './inputs/FormulateInputSlider.vue'
|
||||
import FormulateInputTextArea from './inputs/FormulateInputTextArea.vue'
|
||||
|
||||
/**
|
||||
@ -28,6 +29,7 @@ class Formulate {
|
||||
FormulateInputText,
|
||||
FormulateInputGroup,
|
||||
FormulateInputSelect,
|
||||
FormulateInputSlider,
|
||||
FormulateInputTextArea
|
||||
},
|
||||
library,
|
||||
@ -112,6 +114,8 @@ class Formulate {
|
||||
const generators = this.options.locales[this.options.locale]
|
||||
if (generators.hasOwnProperty(rule)) {
|
||||
return generators[rule](validationContext)
|
||||
} else if (rule[0] === '_' && generators.hasOwnProperty(rule.substr(1))) {
|
||||
return generators[rule.substr(1)](validationContext)
|
||||
}
|
||||
if (generators.hasOwnProperty('default')) {
|
||||
return generators.default(validationContext)
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div
|
||||
class="formulate-input-element formulate-input-element--box"
|
||||
:class="`formulate-input-element formulate-input-element--${context.type}`"
|
||||
:data-type="context.type"
|
||||
>
|
||||
<input
|
||||
|
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
class="formulate-input-element formulate-input-element--select"
|
||||
:class="`formulate-input-element formulate-input-element--${context.type}`"
|
||||
:data-type="context.type"
|
||||
>
|
||||
<select
|
||||
v-model="context.model"
|
||||
|
22
src/inputs/FormulateInputSlider.vue
Normal file
22
src/inputs/FormulateInputSlider.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div
|
||||
:class="`formulate-input-element formulate-input-element--${context.type}`"
|
||||
:data-type="context.type"
|
||||
>
|
||||
<input
|
||||
v-model="context.model"
|
||||
:type="type"
|
||||
v-bind="attributes"
|
||||
@blur="context.blurHandler"
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormulateInputMixin from '../FormulateInputMixin'
|
||||
|
||||
export default {
|
||||
name: 'FormulateInputText',
|
||||
mixins: [FormulateInputMixin]
|
||||
}
|
||||
</script>
|
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
class="formulate-input-element formulate-input-element--textarea"
|
||||
:class="`formulate-input-element formulate-input-element--${context.type}`"
|
||||
:data-type="context.type"
|
||||
>
|
||||
<input
|
||||
v-model="context.model"
|
||||
|
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
class="formulate-input-element formulate-input-element--textarea"
|
||||
data-type="textarea"
|
||||
>
|
||||
<textarea
|
||||
v-model="context.model"
|
||||
|
@ -32,10 +32,6 @@ export default {
|
||||
classification: 'text',
|
||||
component: 'FormulateInputText'
|
||||
},
|
||||
range: {
|
||||
classification: 'text',
|
||||
component: 'FormulateInputText'
|
||||
},
|
||||
search: {
|
||||
classification: 'text',
|
||||
component: 'FormulateInputText'
|
||||
@ -61,6 +57,12 @@ export default {
|
||||
component: 'FormulateInputText'
|
||||
},
|
||||
|
||||
// === SLIDER INPUTS
|
||||
range: {
|
||||
classification: 'slider',
|
||||
component: 'FormulateInputSlider'
|
||||
},
|
||||
|
||||
// === MULTI LINE TEXT INPUTS
|
||||
textarea: {
|
||||
classification: 'textarea',
|
||||
|
@ -1,5 +1,5 @@
|
||||
import isUrl from 'is-url'
|
||||
import { shallowEqualObjects } from './utils'
|
||||
import { shallowEqualObjects, regexForFormat } from './utils'
|
||||
|
||||
/**
|
||||
* Library of rules
|
||||
@ -76,10 +76,16 @@ export default {
|
||||
},
|
||||
|
||||
/**
|
||||
* Rule: ensures the value is a date according to Date.parse()
|
||||
* Rule: ensures the value is a date according to Date.parse(), or a format
|
||||
* regex.
|
||||
*/
|
||||
date: function (value) {
|
||||
return Promise.resolve(!isNaN(Date.parse(value)))
|
||||
date: function (value, format = false) {
|
||||
return Promise.resolve((() => {
|
||||
if (format && typeof format === 'string') {
|
||||
return regexForFormat(format).test(value)
|
||||
}
|
||||
return !isNaN(Date.parse(value))
|
||||
})())
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -145,3 +145,30 @@ function parseRule (rule, rules) {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape a string for use in regular expressions.
|
||||
* @param {string} string
|
||||
*/
|
||||
export function escapeRegExp (string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') // $& means the whole matched string
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string format (date) return a regex to match against.
|
||||
* @param {string} format
|
||||
*/
|
||||
export function regexForFormat (format) {
|
||||
let escaped = `^${escapeRegExp(format)}$`
|
||||
const formats = {
|
||||
MM: '(0[1-9]|1[012])',
|
||||
M: '([1-9]|1[012])',
|
||||
DD: '([012][1-9]|3[01])',
|
||||
D: '([012]?[1-9]|3[01])',
|
||||
YYYY: '\\d{4}',
|
||||
YY: '\\d{2}'
|
||||
}
|
||||
return new RegExp(Object.keys(formats).reduce((regex, format) => {
|
||||
return regex.replace(format, formats[format])
|
||||
}, escaped))
|
||||
}
|
||||
|
@ -58,7 +58,10 @@ export default {
|
||||
/**
|
||||
* Is not a valid date.
|
||||
*/
|
||||
date: function ({ name }) {
|
||||
date: function ({ name, args }) {
|
||||
if (Array.isArray(args) && args.length) {
|
||||
return `${s(name)} is not a valid, please use the format ${args[0]}`
|
||||
}
|
||||
return `${s(name)} is not a valid date.`
|
||||
},
|
||||
|
||||
@ -73,17 +76,20 @@ export default {
|
||||
* Is not a valid email address.
|
||||
*/
|
||||
email: function ({ name, value }) {
|
||||
return `${value} is not a valid email address.`
|
||||
if (!value) {
|
||||
return 'Please enter a valid email address.'
|
||||
}
|
||||
return `“${value}” is not a valid email address.`
|
||||
},
|
||||
|
||||
/**
|
||||
* Value is an allowed value.
|
||||
*/
|
||||
in: function ({ name, value }) {
|
||||
if (typeof value === 'string') {
|
||||
if (typeof value === 'string' && value) {
|
||||
return `“${s(value)}” is not an allowed ${name}.`
|
||||
}
|
||||
return `${s(name)} is not an allowed value.`
|
||||
return `This is not an allowed ${name}.`
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -55,6 +55,7 @@ test('installs on vue instance', () => {
|
||||
'FormulateInputText',
|
||||
'FormulateInputGroup',
|
||||
'FormulateInputSelect',
|
||||
'FormulateInputSlider',
|
||||
'FormulateInputTextArea'
|
||||
]
|
||||
const registry = []
|
||||
|
18
test/FormulateInputSlider.test.js
Normal file
18
test/FormulateInputSlider.test.js
Normal file
@ -0,0 +1,18 @@
|
||||
import Vue from 'vue'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import Formulate from '../src/Formulate.js'
|
||||
import FormulateInput from '../src/FormulateInput.vue'
|
||||
import FormulateInputSlider from '../src/inputs/FormulateInputSlider.vue'
|
||||
|
||||
Vue.use(Formulate)
|
||||
|
||||
/**
|
||||
* Test each type of slider element
|
||||
*/
|
||||
|
||||
describe('FormulateInputSlider', () => {
|
||||
it('renders range input when type is "range"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'range' } })
|
||||
expect(wrapper.contains(FormulateInputSlider)).toBe(true)
|
||||
})
|
||||
})
|
@ -52,11 +52,6 @@ describe('FormulateInputText', () => {
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
it('renders range input when type is "range"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'range' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
})
|
||||
|
||||
it('renders tel input when type is "tel"', () => {
|
||||
const wrapper = mount(FormulateInput, { propsData: { type: 'tel' } })
|
||||
expect(wrapper.contains(FormulateInputText)).toBe(true)
|
||||
|
@ -128,11 +128,16 @@ describe('date', () => {
|
||||
|
||||
it('passes with only month', async () => expect(await rules.date('January')).toBe(false))
|
||||
|
||||
it('passes with valid date format', async () => expect(await rules.date('12/17/1987', 'MM/DD/YYYY')).toBe(true))
|
||||
|
||||
it('fails with simple number and date format', async () => expect(await rules.date('1234', 'MM/DD/YYYY')).toBe(false))
|
||||
|
||||
it('fails with only day of week', async () => expect(await rules.date('saturday')).toBe(false))
|
||||
|
||||
it('fails with random string', async () => expect(await rules.date('Pepsi 17')).toBe(false))
|
||||
|
||||
it('fails with random number', async () => expect(await rules.date('1872301237')).toBe(false))
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { parseRules } from '@/libs/utils'
|
||||
import { parseRules, regexForFormat } from '@/libs/utils'
|
||||
import rules from '@/libs/rules'
|
||||
|
||||
describe('parseRules', () => {
|
||||
@ -42,3 +42,44 @@ describe('parseRules', () => {
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
describe('regexForFormat', () => {
|
||||
it('allows MM format with other characters', () => expect(regexForFormat('abc/MM').test('abc/01')).toBe(true))
|
||||
|
||||
it('fails MM format with single digit', () => expect(regexForFormat('abc/MM').test('abc/1')).toBe(false))
|
||||
|
||||
it('allows M format with single digit', () => expect(regexForFormat('M/abc').test('1/abc')).toBe(true))
|
||||
|
||||
it('fails MM format when out of range', () => expect(regexForFormat('M/abc').test('13/abc')).toBe(false))
|
||||
|
||||
it('fails M format when out of range', () => expect(regexForFormat('M/abc').test('55/abc')).toBe(false))
|
||||
|
||||
it('Replaces double digits before singles', () => expect(regexForFormat('MMM').test('313131')).toBe(false))
|
||||
|
||||
it('allows DD format with zero digit', () => expect(regexForFormat('xyz/DD').test('xyz/01')).toBe(true))
|
||||
|
||||
it('fails DD format with single digit', () => expect(regexForFormat('xyz/DD').test('xyz/9')).toBe(false))
|
||||
|
||||
it('allows D format with single digit', () => expect(regexForFormat('xyz/D').test('xyz/9')).toBe(true))
|
||||
|
||||
it('fails D format with out of range digit', () => expect(regexForFormat('xyz/D').test('xyz/92')).toBe(false))
|
||||
|
||||
it('fails DD format with out of range digit', () => expect(regexForFormat('xyz/D').test('xyz/32')).toBe(false))
|
||||
|
||||
it('allows YY format with double zeros', () => expect(regexForFormat('YY').test('00')).toBe(true))
|
||||
|
||||
it('fails YY format with four zeros', () => expect(regexForFormat('YY').test('0000')).toBe(false))
|
||||
|
||||
it('allows YYYY format with four zeros', () => expect(regexForFormat('YYYY').test('0000')).toBe(true))
|
||||
|
||||
it('allows MD-YY', () => expect(regexForFormat('MD-YY').test('12-00')).toBe(true))
|
||||
|
||||
it('allows DM-YY', () => expect(regexForFormat('DM-YY').test('12-00')).toBe(true))
|
||||
|
||||
it('allows date like MM/DD/YYYY', () => expect(regexForFormat('MM/DD/YYYY').test('12/18/1987')).toBe(true))
|
||||
|
||||
it('allows date like YYYY-MM-DD', () => expect(regexForFormat('YYYY-MM-DD').test('1987-01-31')).toBe(true))
|
||||
|
||||
it('fails date like YYYY-MM-DD with out of bounds day', () => expect(regexForFormat('YYYY-MM-DD').test('1987-01-32')).toBe(false))
|
||||
})
|
||||
|
@ -57,6 +57,57 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Slider inputs
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
&[data-classification='slider'] {
|
||||
input {
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
font-size: 1em;
|
||||
padding: .5em 0;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
@mixin thumb {
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border-radius: 1em;
|
||||
background-color: $formulate-green;
|
||||
margin-top: calc(-.5em + 2px);
|
||||
}
|
||||
|
||||
@mixin track {
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
background-color: $formulate-gray;
|
||||
border-radius: 3px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
@include thumb;
|
||||
}
|
||||
|
||||
&::-moz-range-thumb {
|
||||
@include thumb;
|
||||
}
|
||||
|
||||
&::-ms-thumb {
|
||||
@include thumb;
|
||||
}
|
||||
|
||||
&::-webkit-slider-runnable-track {
|
||||
@include track;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Textarea inputs
|
||||
// -----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user