vendor/assets/javascripts/vue-validator.js in vuejs-1.0.36 vs vendor/assets/javascripts/vue-validator.js in vuejs-1.0.37

- old
+ new

@@ -1,2054 +1,910 @@ -/*! - * vue-validator v3.0.0-alpha.2 - * (c) 2016 kazuya kawaguchi +/** + * vue-validator v1.4.4 + * (c) 2014-2015 kazuya kawaguchi * Released under the MIT License. */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.VueValidator = factory()); -}(this, (function () { 'use strict'; -/* */ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["vue-validator"] = factory(); + else + root["vue-validator"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; -function warn (msg, err) { - if (window.console) { - console.warn('[vue-validator] ' + msg); - if (err) { - console.warn(err.stack); - } - } -} +/******/ // The require function +/******/ function __webpack_require__(moduleId) { -/* */ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; -// validator configrations -var validator = { - classes: {} -}; +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; -var Config = function (Vue) { - // define Vue.config.validator configration - // $FlowFixMe: https://github.com/facebook/flow/issues/285 - Object.defineProperty(Vue.config, 'validator', { - enumerable: true, - configurable: true, - get: function () { return validator }, - set: function (val) { validator = val; } - }); -}; +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/* */ -/** - * build-in validators - */ +/******/ // Flag the module as loaded +/******/ module.loaded = true; -/** - * required - * This function validate whether the value has been filled out. - */ -function required (val, arg) { - var isRequired = arg === undefined ? true : arg; - if (Array.isArray(val)) { - if (val.length !== 0) { - var valid = true; - for (var i = 0, l = val.length; i < l; i++) { - valid = required(val[i], isRequired); - if ((isRequired && !valid) || (!isRequired && valid)) { - break - } - } - return valid - } else { - return !isRequired - } - } else if (typeof val === 'number' || typeof val === 'function') { - return isRequired - } else if (typeof val === 'boolean') { - return val === isRequired - } else if (typeof val === 'string') { - return isRequired ? (val.length > 0) : (val.length <= 0) - } else if (val !== null && typeof val === 'object') { - return isRequired ? (Object.keys(val).length > 0) : (Object.keys(val).length <= 0) - } else if (val === null || val === undefined) { - return !isRequired - } else { - return !isRequired - } -} +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } -/** - * pattern - * This function validate whether the value matches the regex pattern - */ -function pattern (val, pat) { - if (typeof pat !== 'string') { return false } - var match = pat.match(new RegExp('^/(.*?)/([gimy]*)$')); - if (!match) { return false } +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; - return new RegExp(match[1], match[2]).test(val) -} +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; -/** - * minlength - * This function validate whether the minimum length. - */ -function minlength (val, min) { - if (typeof val === 'string') { - return isInteger(min, 10) && val.length >= parseInt(min, 10) - } else if (Array.isArray(val)) { - return val.length >= parseInt(min, 10) - } else { - return false - } -} +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; -/** - * maxlength - * This function validate whether the maximum length. - */ -function maxlength (val, max) { - if (typeof val === 'string') { - return isInteger(max, 10) && val.length <= parseInt(max, 10) - } else if (Array.isArray(val)) { - return val.length <= parseInt(max, 10) - } else { - return false - } -} +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ function(module, exports, __webpack_require__) { -/** - * min - * This function validate whether the minimum value of the numberable value. - */ -function min (val, arg) { - return !isNaN(+(val)) && !isNaN(+(arg)) && (+(val) >= +(arg)) -} + /** + * Import(s) + */ -/** - * max - * This function validate whether the maximum value of the numberable value. - */ -function max (val, arg) { - return !isNaN(+(val)) && !isNaN(+(arg)) && (+(val) <= +(arg)) -} + var validates = __webpack_require__(1) + var _ = __webpack_require__(2) -/** - * isInteger - * This function check whether the value of the string is integer. - */ -function isInteger (val) { - return /^(-?[1-9]\d*|0)$/.test(val) -} + /** + * Export(s) + */ -var validators = Object.freeze({ - required: required, - pattern: pattern, - minlength: minlength, - maxlength: maxlength, - min: min, - max: max -}); + module.exports = install -/* */ -var Asset = function (Vue) { - var ref = Vue.util; - var extend = ref.extend; - // set global validators asset - var assets = Object.create(null); - extend(assets, validators); - Vue.options.validators = assets; + /** + * Install plugin + */ - // set option merge strategy - var strats = Vue.config.optionMergeStrategies; - if (strats) { - strats.validators = function (parent, child) { - if (!child) { return parent } - if (!parent) { return child } - var ret = Object.create(null); - extend(ret, parent); - var key; - for (key in child) { - ret[key] = child[key]; - } - return ret - }; - } + function install (Vue, options) { + options = options || {} + var componentName = options.component = options.component || '$validator' + var directiveName = options.directive = options.directive || 'validate' + var path = Vue.parsers.path + var util = Vue.util - /** - * Register or retrieve a global validator definition. - */ - function validator ( - id, - def - ) { - if (def === undefined) { - return Vue.options['validators'][id] - } else { - Vue.options['validators'][id] = def; - if (def === null) { - delete Vue.options['validators']['id']; - } - } - } - Vue['validator'] = validator; -}; -/* */ + // custom validators merge strategy setting + Vue.config.optionMergeStrategies.validator = function (parent, child, vm, k) { + var validatorOptions = { validates: {}, namespace: {} } + if (!parent && !child) { + return validatorOptions + } else if (!parent && child) { + util.extend(validatorOptions['validates'], child['validates']) + util.extend(validatorOptions['namespace'], child['namespace']) + return validatorOptions + } else if (parent && !child) { + util.extend(validatorOptions['validates'], parent['validates']) + util.extend(validatorOptions['namespace'], parent['namespace']) + return validatorOptions + } else if (parent && child) { + var key + if ('validates' in parent) { + util.extend(validatorOptions['validates'], parent['validates']) + } + if ('namespace' in parent) { + util.extend(validatorOptions['namespace'], parent['namespace']) + } + if ('validates' in child) { + for (key in child['validates']) { + if ('validates' in parent && !parent['validates'].hasOwnProperty(key)) { + validatorOptions['validates'][key] = child['validates'][key] + } + } + } + if ('namespace' in child) { + for (key in child['namespace']) { + if ('namespace' in parent && !parent['namespace'].hasOwnProperty(key)) { + validatorOptions['namespace'][key] = child['namespace'][key] + } + } + } + return validatorOptions + } else { + _.warn('unexpected validator option merge strategy') + return validatorOptions + } + } -var Group = function (Vue) { - var ref = Vue.util; - var extend = ref.extend; - return { - data: function data () { - return { - valid: true, - dirty: false, - touched: false, - modified: false, - results: {} - } - }, - computed: { - invalid: function invalid () { return !this.valid }, - pristine: function pristine () { return !this.dirty }, - untouched: function untouched () { return !this.touched }, - result: function result () { - var ret = { - valid: this.valid, - invalid: this.invalid, - dirty: this.dirty, - pristine: this.pristine, - touched: this.touched, - untouched: this.untouched, - modified: this.modified - }; - var results = this.results; - this._validityKeys.forEach(function (key) { - ret[key] = results[key]; - if (ret[key].errors) { - var errors = ret.errors || []; - ret[key].errors.forEach(function (error) { - errors.push(error); - }); - ret.errors = errors; - } - }); - return ret - } - }, - watch: { - results: function results (val, old) { - var keys = this._validityKeys; - var results = this.results; - this.valid = this.checkResults(keys, results, 'valid', true); - this.dirty = this.checkResults(keys, results, 'dirty', false); - this.touched = this.checkResults(keys, results, 'touched', false); - this.modified = this.checkResults(keys, results, 'modified', false); - } - }, - created: function created () { - this._validities = Object.create(null); - this._validityWatchers = Object.create(null); - this._validityKeys = []; - this._committing = false; - }, - destroyed: function destroyed () { - var this$1 = this; + function getVal (obj, keypath) { + var ret = null + try { + ret = path.get(obj, keypath) + } catch (e) { } + return ret + } - this._validityKeys.forEach(function (key) { - this$1._validityWatchers[key](); - delete this$1._validityWatchers[key]; - delete this$1._validities[key]; - }); - delete this._validityWatchers; - delete this._validities; - delete this._validityKeys; - }, - methods: { - register: function register (name, validity) { - var this$1 = this; - this._validities[name] = validity; - this._validityKeys = Object.keys(this._validities); - this.setResults(name, {}); - this.withCommit(function () { - this$1._validityWatchers[name] = validity.$watch('result', function (val, old) { - this$1.setResults(name, val); - }, { deep: true, immediate: true }); - }); - }, - unregister: function unregister (name) { - var this$1 = this; + Vue.directive(directiveName, { - this._validityWatchers[name](); - delete this._validityWatchers[name]; - delete this._validities[name]; - this._validityKeys = Object.keys(this._validities); - this.withCommit(function () { - this$1.resetResults(name); - }); - }, - validityCount: function validityCount () { - return this._validityKeys.length - }, - isRegistered: function isRegistered (name) { - return name in this._validities - }, - getValidityKeys: function getValidityKeys () { - return this._validityKeys - }, - checkResults: function checkResults ( - keys, - results, - prop, - checking - ) { - var ret = checking; - for (var i = 0; i < keys.length; i++) { - var result = results[keys[i]]; - if (result[prop] !== checking) { - ret = !checking; - break - } - } - return ret - }, - setResults: function setResults (name, val) { - var this$1 = this; + priority: 1024, - var newVal = {}; - this._validityKeys.forEach(function (key) { - newVal[key] = extend({}, this$1.results[key]); - }); - newVal[name] = extend({}, val); - this.results = newVal; - }, - resetResults: function resetResults (ignore) { - var this$1 = this; + bind: function () { + var vm = this.vm + var el = this.el + var $validator = vm[componentName] + var keypath = this._keypath = this._parseModelAttribute(el.getAttribute(Vue.config.prefix + 'model')) + var validator = this.arg ? this.arg : this.expression + var arg = this.arg ? this.expression : null - var newVal = {}; - this._validityKeys.forEach(function (key) { - if (ignore && ignore !== key) { - newVal[key] = extend({}, this$1.results[key]); - } - }); - this.results = newVal; - }, - withCommit: function withCommit (fn) { - var committing = this._committing; - this._committing = true; - fn(); - this._committing = committing; - } - } - } -}; + var customs = _.getCustomValidators(vm.$options) + if (!this._checkValidator(validator, validates, customs)) { + _.warn("specified invalid '" + + validator + "' validator at v-validate directive !! please check '" + + validator + "' validator !!") + this._ignore = true + return + } -/* */ -var ValidationClass = function (Vue) { - var ValidityGroup = Group(Vue); + if (!$validator) { + vm[componentName] = $validator = vm.$addChild( + {}, // null option + Vue.extend(__webpack_require__(3)) + ) + } - var Validation = function Validation (options) { - if ( options === void 0 ) options = {}; + var value = el.getAttribute('value') + if (el.getAttribute('number') !== null) { + value = util.toNumber(value) + } + this._init = value - this._result = {}; - this._host = options.host; - this._named = Object.create(null); - this._group = Object.create(null); - this._validities = Object.create(null); - this._beginDestroy = false; - Vue.util.defineReactive(this._host, '$validation', this._result); - }; + var validation = $validator._getValidationNamespace('validation') + var init = value || vm.$get(keypath) + var readyEvent = el.getAttribute('wait-for') - Validation.prototype.register = function register ( - field, - validity, - options - ) { - if ( options === void 0 ) options = {}; + if (readyEvent && !$validator._isRegistedReadyEvent(keypath)) { + $validator._addReadyEvents(keypath, this._checkParam('wait-for')) + } - // NOTE: lazy setup (in constructor, occured callstack recursive errors ...) - if (!this._validityManager) { - this._validityManager = new Vue(ValidityGroup); - this._watchValidityResult(); - } + this._setupValidator($validator, keypath, validation, validator, el, arg, init) + }, - if (this._validities[field]) { - // TODO: should be output console.error - return - } - this._validities[field] = validity; + update: function (val, old) { + if (this._ignore) { return } - var named = options.named; - var group = options.group; - var groupValidity = group - ? this._getValidityGroup('group', group) || this._registerValidityGroup('group', group) - : null; - var namedValidity = named - ? this._getValidityGroup('named', named) || this._registerValidityGroup('named', named) - : null; - if (named && group && namedValidity && groupValidity) { - groupValidity.register(field, validity); - !namedValidity.isRegistered(group) && namedValidity.register(group, groupValidity); - !this._validityManager.isRegistered(named) && this._validityManager.register(named, namedValidity); - } else if (namedValidity) { - namedValidity.register(field, validity); - !this._validityManager.isRegistered(named) && this._validityManager.register(named, namedValidity); - } else if (groupValidity) { - groupValidity.register(field, validity); - !this._validityManager.isRegistered(group) && this._validityManager.register(group, groupValidity); - } else { - this._validityManager.register(field, validity); - } - }; + var self = this + var vm = this.vm + var keypath = this._keypath + var validator = this.arg ? this.arg : this.expression + var $validator = vm[componentName] - Validation.prototype.unregister = function unregister ( - field, - options - ) { - if ( options === void 0 ) options = {}; + $validator._changeValidator(keypath, validator, val) + if (!$validator._isRegistedReadyEvent(keypath)) { // normal + this._updateValidator($validator, validator, keypath) + } else { // wait-for + vm.$once($validator._getReadyEvents(keypath), function (val) { + $validator._setInitialValue(keypath, val) + vm.$set(keypath, val) + self._updateValidator($validator, validator, keypath) + }) + } + }, - if (!this._validityManager) { - // TODO: should be output error - return - } - if (!this._validities[field]) { - // TODO: should be output error - return - } - delete this._validities[field]; + unbind: function () { + if (this._ignore) { return } - var named = options.named; - var group = options.group; - var groupValidity = group ? this._getValidityGroup('group', group) : null; - var namedValidity = named ? this._getValidityGroup('named', named) : null; - if (named && group && namedValidity && groupValidity) { - groupValidity.unregister(field); - if (groupValidity.validityCount() === 0) { - namedValidity.isRegistered(group) && namedValidity.unregister(group); - this._unregisterValidityGroup('group', group); - } - if (namedValidity.validityCount() === 0) { - this._validityManager.isRegistered(named) && this._validityManager.unregister(named); - this._unregisterValidityGroup('named', named); - } - } else if (named && namedValidity) { - namedValidity.unregister(field); - if (namedValidity.validityCount() === 0) { - this._validityManager.isRegistered(named) && this._validityManager.unregister(named); - this._unregisterValidityGroup('named', named); - } - } else if (group && groupValidity) { - groupValidity.unregister(field); - if (groupValidity.validityCount() === 0) { - this._validityManager.isRegistered(group) && this._validityManager.unregister(group); - this._unregisterValidityGroup('group', group); - } - } else { - this._validityManager.unregister(field); - } - }; + var vm = this.vm + var keypath = this._keypath + var validator = this.arg ? this.arg : this.expression + var $validator = vm[componentName] - Validation.prototype.destroy = function destroy () { - var this$1 = this; + this._teardownValidator(vm, $validator, keypath, validator) + }, - var validityKeys = Object.keys(this._validities); - var namedKeys = Object.keys(this._named); - var groupKeys = Object.keys(this._group); + _parseModelAttribute: function (attr) { + var res = Vue.parsers.directive.parse(attr) + return res[0].arg ? res[0].arg : res[0].expression + }, - // unregister validity - validityKeys.forEach(function (validityKey) { - groupKeys.forEach(function (groupKey) { - var group = this$1._getValidityGroup('group', groupKey); - if (group && group.isRegistered(groupKey)) { - group.unregister(validityKey); - } - }); - namedKeys.forEach(function (namedKey) { - var named = this$1._getValidityGroup('named', namedKey); - if (named && named.isRegistered(validityKey)) { - named.unregister(validityKey); - } - }); - if (this$1._validityManager.isRegistered(validityKey)) { - this$1._validityManager.unregister(validityKey); - } - delete this$1._validities[validityKey]; - }); + _checkValidator: function (validator, validates, customs) { + var items = Object.keys(validates).concat(Object.keys(customs)) + return items.some(function (item) { + return item === validator + }) + }, - // unregister grouped validity - groupKeys.forEach(function (groupKey) { - namedKeys.forEach(function (namedKey) { - var named = this$1._getValidityGroup('named', namedKey); - if (named && named.isRegistered(groupKey)) { - named.unregister(groupKey); - } - }); - if (this$1._validityManager.isRegistered(groupKey)) { - this$1._validityManager.unregister(groupKey); - } - this$1._unregisterValidityGroup('group', groupKey); - }); + _setupValidator: function ($validator, keypath, validation, validator, el, arg, init) { + var vm = this.vm - // unregister named validity - namedKeys.forEach(function (namedKey) { - if (this$1._validityManager.isRegistered(namedKey)) { - this$1._validityManager.unregister(namedKey); - } - this$1._unregisterValidityGroup('named', namedKey); - }); + if (!getVal($validator[validation], keypath)) { + $validator._defineModelValidationScope(keypath) + if (el.tagName === 'INPUT' && el.type === 'radio') { + if (getVal(vm, keypath) === init) { + $validator._setInitialValue(keypath, init) + } + } else { + $validator._setInitialValue(keypath, init) + } + } - this._beginDestroy = true; - }; + if (!getVal($validator[validation], [keypath, validator].join('.'))) { + $validator._defineValidatorToValidationScope(keypath, validator) + $validator._addValidator(keypath, validator, getVal(vm, arg) || arg) + } + }, - Validation.prototype._getValidityGroup = function _getValidityGroup (type, name) { - return type === 'named' ? this._named[name] : this._group[name] - }; + _updateValidator: function ($validator, validator, keypath) { + var value = $validator.$get(keypath) + var el = this.el - Validation.prototype._registerValidityGroup = function _registerValidityGroup (type, name) { - var groups = type === 'named' ? this._named : this._group; - groups[name] = new Vue(ValidityGroup); - return groups[name] - }; + if (this._init) { + value = this._init + delete this._init + } - Validation.prototype._unregisterValidityGroup = function _unregisterValidityGroup (type, name) { - var groups = type === 'named' ? this._named : this._group; - if (!groups[name]) { - // TODO: should be warn - return - } + if (el.tagName === 'INPUT' && el.type === 'radio') { + if (value === $validator.$get(keypath)) { + $validator._updateDirtyProperty(keypath, value) + } + } else { + $validator._updateDirtyProperty(keypath, value) + } - groups[name].$destroy(); - delete groups[name]; - }; + $validator._doValidate(keypath, validator, $validator.$get(keypath)) + }, - Validation.prototype._watchValidityResult = function _watchValidityResult () { - var this$1 = this; + _teardownValidator: function (vm, $validator, keypath, validator) { + $validator._undefineValidatorToValidationScope(keypath, validator) + $validator._undefineModelValidationScope(keypath, validator) + } + }) + } - this._watcher = this._validityManager.$watch('results', function (val, old) { - Vue.set(this$1._host, '$validation', val); - if (this$1._beginDestroy) { - this$1._destroyValidityMananger(); - } - }, { deep: true }); - }; - Validation.prototype._unwatchValidityResult = function _unwatchValidityResult () { - this._watcher(); - delete this._watcher; - }; +/***/ }, +/* 1 */ +/***/ function(module, exports) { - Validation.prototype._destroyValidityMananger = function _destroyValidityMananger () { - this._unwatchValidityResult(); - this._validityManager.$destroy(); - this._validityManager = null; - }; + /** + * Fundamental validate functions + */ - return Validation -}; -/* */ + /** + * required + * + * This function validate whether the value has been filled out. + * + * @param val + * @return {Boolean} + */ -var Mixin = function (Vue) { - var Validation = ValidationClass(Vue); + function required (val) { + if (Array.isArray(val)) { + return val.length > 0 + } else if (typeof val === 'number') { + return true + } else if ((val !== null) && (typeof val === 'object')) { + return Object.keys(val).length > 0 + } else { + return !val + ? false + : true + } + } - return { - beforeCreate: function beforeCreate () { - this._validation = new Validation({ host: this }); - } - } -}; -/* */ + /** + * pattern + * + * This function validate whether the value matches the regex pattern + * + * @param val + * @param {String} pat + * @return {Boolean} + */ -var baseProps = { - field: { - type: String, - required: true - }, - validators: { - type: [String, Array, Object], - required: true - }, - group: { - type: String - }, - multiple: { - type: Boolean - }, - autotouch: { - type: String, - default: function () { - return 'on' - } - }, - classes: { - type: Object, - default: function () { - return {} - } - } -}; + function pattern (val, pat) { + if (typeof pat !== 'string') { return false } -var DEFAULT_CLASSES = { - valid: 'valid', - invalid: 'invalid', - touched: 'touched', - untouched: 'untouched', - pristine: 'pristine', - dirty: 'dirty', - modified: 'modified' -}; + var match = pat.match(new RegExp('^/(.*?)/([gimy]*)$')) + if (!match) { return false } -/* */ -var States = function (Vue) { - var ref = Vue.util; - var extend = ref.extend; - var isPlainObject = ref.isPlainObject; + return new RegExp(match[1], match[2]).test(val) + } - function initialStates (states, validators, init) { - if ( init === void 0 ) init = undefined; - if (Array.isArray(validators)) { - validators.forEach(function (validator) { - states[validator] = init; - }); - } else { - Object.keys(validators).forEach(function (validator) { - var props = (validators[validator] && - validators[validator]['props'] && - isPlainObject(validators[validator]['props'])) - ? validators[validator]['props'] - : null; - if (props) { - Object.keys(props).forEach(function (prop) { - states[validator] = {}; - states[validator][prop] = init; - }); - } else { - states[validator] = init; - } - }); - } - } + /** + * minLength + * + * This function validate whether the minimum length of the string. + * + * @param {String} val + * @param {String|Number} min + * @return {Boolean} + */ - function getInitialResults (validators) { - var results = {}; - initialStates(results, validators, undefined); - return results - } + function minLength (val, min) { + return typeof val === 'string' && + isInteger(min, 10) && + val.length >= parseInt(min, 10) + } - function getInitialProgresses (validators) { - var progresses = {}; - initialStates(progresses, validators, ''); - return progresses - } - var props = extend({ - child: { - type: Object, - required: true - }, - value: { - type: Object - } - }, baseProps); + /** + * maxLength + * + * This function validate whether the maximum length of the string. + * + * @param {String} val + * @param {String|Number} max + * @return {Boolean} + */ - function data () { - var validators = nomalizeValidators(this.validators); - return { - results: getInitialResults(validators), - valid: true, - dirty: false, - touched: false, - modified: false, - progresses: getInitialProgresses(validators) - } - } + function maxLength (val, max) { + return typeof val === 'string' && + isInteger(max, 10) && + val.length <= parseInt(max, 10) + } - return { - props: props, - data: data - } -}; -function nomalizeValidators (target) { - return typeof target === 'string' ? [target] : target -} + /** + * min + * + * This function validate whether the minimum value of the numberable value. + * + * @param {*} val + * @param {*} arg minimum + * @return {Boolean} + */ -/* */ + function min (val, arg) { + return !isNaN(+(val)) && !isNaN(+(arg)) && (+(val) >= +(arg)) + } -var Computed = function (Vue) { - var ref = Vue.util; - var isPlainObject = ref.isPlainObject; - function setError ( - result, - field, - validator, - message, - prop - ) { - var error = { field: field, validator: validator }; - if (message) { - error.message = message; - } - if (prop) { - error.prop = prop; - } - result.errors = result.errors || []; - result.errors.push(error); - } + /** + * max + * + * This function validate whether the maximum value of the numberable value. + * + * @param {*} val + * @param {*} arg maximum + * @return {Boolean} + */ - function walkProgresses (keys, target) { - var progress = ''; - for (var i = 0; i < keys.length; i++) { - var result = target[keys[i]]; - if (typeof result === 'string' && result) { - progress = result; - break - } - if (isPlainObject(result)) { - var nestedKeys = Object.keys(result); - progress = walkProgresses(nestedKeys, result); - if (!progress) { - break - } - } - } - return progress - } + function max (val, arg) { + return !isNaN(+(val)) && !isNaN(+(arg)) && (+(val) <= +(arg)) + } - function invalid () { - return !this.valid - } - function pristine () { - return !this.dirty - } + /** + * isInteger + * + * This function check whether the value of the string is integer. + * + * @param {String} val + * @return {Boolean} + * @private + */ - function untouched () { - return !this.touched - } + function isInteger (val) { + return /^(-?[1-9]\d*|0)$/.test(val) + } - function result () { - var this$1 = this; - var ret = { - valid: this.valid, - invalid: this.invalid, - dirty: this.dirty, - pristine: this.pristine, - touched: this.touched, - untouched: this.untouched, - modified: this.modified - }; + /** + * export(s) + */ + module.exports = { + required: required, + pattern: pattern, + minLength: minLength, + maxLength: maxLength, + min: min, + max: max + } - var keys = this._keysCached(this._uid.toString(), this.results); - keys.forEach(function (validator) { - var result = this$1.results[validator]; - if (typeof result === 'boolean') { - if (result) { - ret[validator] = false; - } else { - setError(ret, this$1.field, validator); - ret[validator] = !result; - } - } else if (typeof result === 'string') { - setError(ret, this$1.field, validator, result); - ret[validator] = result; - } else if (isPlainObject(result)) { // object - var props = Object.keys(result); - props.forEach(function (prop) { - var propRet = result[prop]; - ret[prop] = ret[prop] || {}; - if (typeof propRet === 'boolean') { - if (propRet) { - ret[prop][validator] = false; - } else { - setError(ret, this$1.field, validator, undefined, prop); - ret[prop][validator] = !propRet; - } - } else if (typeof propRet === 'string') { - setError(ret, this$1.field, validator, propRet, prop); - ret[prop][validator] = propRet; - } else { - ret[prop][validator] = false; - } - }); - } else { - ret[validator] = false; - } - }); - return ret - } +/***/ }, +/* 2 */ +/***/ function(module, exports) { - function progress () { - var ret = ''; - ret = walkProgresses( - this._keysCached(this._uid.toString(), this.results), - this.progresses - ); - return ret - } + /** + * Utilties + */ - return { - invalid: invalid, - pristine: pristine, - untouched: untouched, - result: result, - progress: progress - } -}; -/* */ + /** + * warn + * + * @param {String} msg + * @param {Error} [err] + * + */ -var Render = function (Vue) { - return { - render: function render (h) { - return this.child - } - } -}; + exports.warn = function (msg, err) { + if (window.console) { + console.warn('[vue-validator] ' + msg) + if (err) { + console.warn(err.stack) + } + } + } -/* */ + /** + * Get target validatable object + * + * @param {Object} validation + * @param {String} keypath + * @return {Object} validatable object + */ -var SingleElementClass = function (Vue) { - var ref = Vue.util; - var looseEqual = ref.looseEqual; + exports.getTarget = function (validation, keypath) { + var last = validation + var keys = keypath.split('.') + var key, obj + for (var i = 0; i < keys.length; i++) { + key = keys[i] + obj = last[key] + last = obj + if (!last) { + break + } + } + return last + } - var SingleElement = function SingleElement (vm) { - this._vm = vm; - this.initValue = this.getValue(); - this.attachValidity(); - }; + /** + * Get custom validators + * + * @param {Object} options + * @return {Object} + */ - SingleElement.prototype.attachValidity = function attachValidity () { - this._vm.$el.$validity = this._vm; - }; + exports.getCustomValidators = function (options) { + var opts = options + var validators = {} + var key + var context + do { + if (opts['validator'] && opts['validator']['validates']) { + for (key in opts['validator']['validates']) { + if (!validators.hasOwnProperty(key)) { + validators[key] = opts['validator']['validates'][key] + } + } + } + context = opts._context || opts._parent + if (context) { + opts = context.$options + } + } while (context || opts._parent) + return validators + } - SingleElement.prototype.getValue = function getValue () { - var el = this._vm.$el; - if (el.tagName === 'SELECT') { - return getSelectValue(el) - } else { - if (el.type === 'checkbox') { - return el.checked - } else { - return el.value - } - } - }; - SingleElement.prototype.checkModified = function checkModified () { - var el = this._vm.$el; - if (el.tagName === 'SELECT') { - return !looseEqual(this.initValue, getSelectValue(el)) - } else { - if (el.type === 'checkbox') { - return !looseEqual(this.initValue, el.checked) - } else { - return !looseEqual(this.initValue, el.value) - } - } - }; +/***/ }, +/* 3 */ +/***/ function(module, exports, __webpack_require__) { - SingleElement.prototype.listenToucheableEvent = function listenToucheableEvent () { - this._vm.$el.addEventListener('focusout', this._vm.willUpdateTouched); - }; + /** + * Import(s) + */ - SingleElement.prototype.unlistenToucheableEvent = function unlistenToucheableEvent () { - this._vm.$el.removeEventListener('focusout', this._vm.willUpdateTouched); - }; + var validates = __webpack_require__(1) + var _ = __webpack_require__(2) - SingleElement.prototype.listenInputableEvent = function listenInputableEvent () { - var vm = this._vm; - var el = vm.$el; - if (el.tagName === 'SELECT') { - el.addEventListener('change', vm.handleInputable); - } else { - if (el.type === 'checkbox') { - el.addEventListener('change', vm.handleInputable); - } else { - el.addEventListener('input', vm.handleInputable); - } - } - }; - SingleElement.prototype.unlistenInputableEvent = function unlistenInputableEvent () { - var vm = this._vm; - var el = vm.$el; - if (el.tagName === 'SELECT') { - el.removeEventListener('change', vm.handleInputable); - } else { - if (el.type === 'checkbox') { - el.removeEventListener('change', vm.handleInputable); - } else { - el.removeEventListener('input', vm.handleInputable); - } - } - }; + /** + * Export(s) + */ - return SingleElement -}; -function getSelectValue (el) { - var value = []; - for (var i = 0, l = el.options.length; i < l; i++) { - var option = el.options[i]; - if (!option.disabled && option.selected) { - value.push(option.value); - } - } - return value -} + /** + * `v-validator` component with mixin + */ -/* */ + module.exports = { + inherit: true, -var MultiElementClass = function (Vue) { - var ref = Vue.util; - var looseEqual = ref.looseEqual; + created: function () { + this._initValidationVariables() + this._initOptions() + this._mixinCustomValidates() + this._defineProperties() + this._defineValidationScope() + }, - var MultiElement = function MultiElement (vm) { - // TODO: should be checked whether included radio or checkbox - this._vm = vm; - this.initValue = this.getValue(); - this.attachValidity(); - }; + methods: { + _getValidationNamespace: function (key) { + return this._namespace[key] + }, - MultiElement.prototype.attachValidity = function attachValidity () { - var this$1 = this; + _initValidationVariables: function () { + this._validators = {} + this._validates = {} + this._initialValues = {} + for (var key in validates) { + this._validates[key] = validates[key] + } + this._validatorWatchers = {} + this._readyEvents = {} + }, - this._vm.$el.$validity = this._vm; - this._eachItems(function (item) { - item.$validity = this$1._vm; - }); - }; + _initOptions: function () { + this._namespace = getCustomNamespace(this.$options) + this._namespace.validation = this._namespace.validation || 'validation' + this._namespace.valid = this._namespace.valid || 'valid' + this._namespace.invalid = this._namespace.invalid || 'invalid' + this._namespace.dirty = this._namespace.dirty || 'dirty' + }, - MultiElement.prototype.getValue = function getValue () { - return this._getCheckedValue() - }; + _mixinCustomValidates: function () { + var customs = _.getCustomValidators(this.$options) + for (var key in customs) { + this._validates[key] = customs[key] + } + }, - MultiElement.prototype.checkModified = function checkModified () { - return !looseEqual(this.initValue, this._getCheckedValue()) - }; + _defineValidProperty: function (target, getter) { + Object.defineProperty(target, this._getValidationNamespace('valid'), { + enumerable: true, + configurable: true, + get: getter + }) + }, - MultiElement.prototype.listenToucheableEvent = function listenToucheableEvent () { - var this$1 = this; + _undefineValidProperty: function (target) { + delete target[this._getValidationNamespace('valid')] + }, - this._eachItems(function (item) { - item.addEventListener('focusout', this$1._vm.willUpdateTouched); - }); - }; + _defineInvalidProperty: function (target) { + var self = this + Object.defineProperty(target, this._getValidationNamespace('invalid'), { + enumerable: true, + configurable: true, + get: function () { + return !target[self._getValidationNamespace('valid')] + } + }) + }, - MultiElement.prototype.unlistenToucheableEvent = function unlistenToucheableEvent () { - var this$1 = this; + _undefineInvalidProperty: function (target) { + delete target[this._getValidationNamespace('invalid')] + }, - this._eachItems(function (item) { - item.removeEventListener('focusout', this$1._vm.willUpdateTouched); - }); - }; + _defineDirtyProperty: function (target, getter) { + Object.defineProperty(target, this._getValidationNamespace('dirty'), { + enumerable: true, + configurable: true, + get: getter + }) + }, - MultiElement.prototype.listenInputableEvent = function listenInputableEvent () { - var this$1 = this; + _undefineDirtyProperty: function (target) { + delete target[this._getValidationNamespace('dirty')] + }, - this._eachItems(function (item) { - item.addEventListener('change', this$1._vm.handleInputable); - }); - }; + _defineProperties: function () { + var self = this - MultiElement.prototype.unlistenInputableEvent = function unlistenInputableEvent () { - var this$1 = this; + var walk = function (obj, propName, namespaces) { + var ret = false + var keys = Object.keys(obj) + var i = keys.length + var key, last + while (i--) { + key = keys[i] + last = obj[key] + if (!(key in namespaces) && typeof last === 'object') { + ret = walk(last, propName, namespaces) + if ((propName === self._getValidationNamespace('valid') && !ret) || + (propName === self._getValidationNamespace('dirty') && ret)) { + break + } + } else if (key === propName && typeof last !== 'object') { + ret = last + if ((key === self._getValidationNamespace('valid') && !ret) || + (key === self._getValidationNamespace('dirty') && ret)) { + break + } + } + } + return ret + } - this._eachItems(function (item) { - item.removeEventListener('change', this$1._vm.handleInputable); - }); - }; + this._defineValidProperty(this.$parent, function () { + var validationName = self._getValidationNamespace('validation') + var validName = self._getValidationNamespace('valid') + return walk(this[validationName], validName, self._namespace) + }) - MultiElement.prototype._getCheckedValue = function _getCheckedValue () { - var value = []; - this._eachItems(function (item) { - if (!item.disabled && item.checked) { - value.push(item.value); - } - }); - return value - }; + this._defineInvalidProperty(this.$parent) - MultiElement.prototype._getItems = function _getItems () { - return this._vm.$el.querySelectorAll('input[type="checkbox"], input[type="radio"]') - }; + this._defineDirtyProperty(this.$parent, function () { + var validationName = self._getValidationNamespace('validation') + var dirtyName = self._getValidationNamespace('dirty') + return walk(this[validationName], dirtyName, self._namespace) + }) + }, - MultiElement.prototype._eachItems = function _eachItems (cb) { - var items = this._getItems(); - for (var i = 0; i < items.length; i++) { - cb(items[i]); - } - }; + _undefineProperties: function () { + this._undefineDirtyProperty(this.$parent) + this._undefineInvalidProperty(this.$parent) + this._undefineValidProperty(this.$parent) + }, - return MultiElement -}; + _defineValidationScope: function () { + this.$parent.$add(this._getValidationNamespace('validation'), {}) + }, -/* */ + _undefineValidationScope: function () { + var validationName = this._getValidationNamespace('validation') + this.$parent.$delete(validationName) + }, -var inBrowser = - typeof window !== 'undefined' && - Object.prototype.toString.call(window) !== '[object Object]'; -var UA = inBrowser && window.navigator.userAgent.toLowerCase(); -var isIE9 = UA && UA.indexOf('msie 9.0') > 0; + _defineModelValidationScope: function (keypath) { + var self = this + var validationName = this._getValidationNamespace('validation') + var dirtyName = this._getValidationNamespace('dirty') -function getClass (el) { - var classname = el.className; - if (typeof classname === 'object') { - classname = classname.baseVal || ''; - } - return classname -} + var keys = keypath.split('.') + var last = this[validationName] + var obj, key + for (var i = 0; i < keys.length; i++) { + key = keys[i] + obj = last[key] + if (!obj) { + obj = {} + last.$add(key, obj) + } + last = obj + } + last.$add(dirtyName, false) -function setClass (el, cls) { - if (isIE9 && !/svg$/.test(el.namespaceURI)) { - el.className = cls; - } else { - el.setAttribute('class', cls); - } -} + this._defineValidProperty(last, function () { + var ret = true + var validators = self._validators[keypath] + var i = validators.length + var validator + while (i--) { + validator = validators[i] + if (last[validator.name]) { + ret = false + break + } + } + return ret + }) + this._defineInvalidProperty(last) -function addClass (el, cls) { - if (el.classList) { - el.classList.add(cls); - } else { - var cur = ' ' + getClass(el) + ' '; - if (cur.indexOf(' ' + cls + ' ') < 0) { - setClass(el, (cur + cls).trim()); - } - } -} + this._validators[keypath] = [] -function removeClass (el, cls) { - if (el.classList) { - el.classList.remove(cls); - } else { - var cur = ' ' + getClass(el) + ' '; - var tar = ' ' + cls + ' '; - while (cur.indexOf(tar) >= 0) { - cur = cur.replace(tar, ' '); - } - setClass(el, cur.trim()); - } - if (!el.className) { - el.removeAttribute('class'); - } -} + this._watchModel(keypath, function (val, old) { + self._updateDirtyProperty(keypath, val) + self._validators[keypath].forEach(function (validator) { + self._doValidate(keypath, validator.name, val) + }) + }) + }, -function toggleClasses (el, key, fn) { - if (!el) { return } + _undefineModelValidationScope: function (keypath, validator) { + if (this.$parent) { + var targetPath = [this._getValidationNamespace('validation'), keypath].join('.') + var target = this.$parent.$get(targetPath) + if (target && Object.keys(target).length === 3 && + this._getValidationNamespace('valid') in target && + this._getValidationNamespace('invalid') in target && + this._getValidationNamespace('dirty') in target) { + this._unwatchModel(keypath) + this._undefineDirtyProperty(target) + this._undefineInvalidProperty(target) + this._undefineValidProperty(target) + removeValidationProperties( + this.$parent.$get(this._getValidationNamespace('validation')), + keypath + ) + } + } + }, - key = key.trim(); - if (key.indexOf(' ') === -1) { - fn(el, key); - return - } + _defineValidatorToValidationScope: function (keypath, validator) { + var target = _.getTarget(this[this._getValidationNamespace('validation')], keypath) + target.$add(validator, null) + }, - var keys = key.split(/\s+/); - for (var i = 0, l = keys.length; i < l; i++) { - fn(el, keys[i]); - } -} + _undefineValidatorToValidationScope: function (keypath, validator) { + var validationName = this._getValidationNamespace('validation') + if (this.$parent) { + var targetPath = [validationName, keypath].join('.') + var target = this.$parent.$get(targetPath) + if (target) { + target.$delete(validator) + } + } + }, -function memoize (fn) { - var cache = Object.create(null); - return function memoizeFn (id) { - var args = [], len = arguments.length - 1; - while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; + _getInitialValue: function (keypath) { + return this._initialValues[keypath] + }, - var hit = cache[id]; - return hit || (cache[id] = fn.apply(void 0, args)) - } -} + _setInitialValue: function (keypath, val) { + this._initialValues[keypath] = val + }, -/* */ -var ComponentElementClass = function (Vue) { - var ref = Vue.util; - var looseEqual = ref.looseEqual; - var isPlainObject = ref.isPlainObject; + _addValidator: function (keypath, validator, arg) { + this._validators[keypath].push({ name: validator, arg: arg }) + }, - function getValidatorProps (validators) { - var normalized = typeof validators === 'string' ? [validators] : validators; - var targets = []; - if (isPlainObject(normalized)) { - Object.keys(normalized).forEach(function (validator) { - var props = (normalized[validator] && - normalized[validator]['props'] && - isPlainObject(normalized[validator]['props'])) - ? normalized[validator]['props'] - : null; - if (props) { - Object.keys(props).forEach(function (prop) { - if (!~targets.indexOf(prop)) { - targets.push(prop); - } - }); - } - }); - } - return targets - } + _changeValidator: function (keypath, validator, arg) { + var validators = this._validators[keypath] + var i = validators.length + while (i--) { + if (validators[i].name === validator) { + validators[i].arg = arg + break + } + } + }, - var ComponentElement = function ComponentElement (vm, vnode, validatorProps) { - this._vm = vm; - this._vnode = vnode; - this._validatorProps = validatorProps || memoize(getValidatorProps); - this.initValue = this.getValue(); - this._watchers = []; - this.attachValidity(); - }; + _findValidator: function (keypath, validator) { + var found = null + var validators = this._validators[keypath] + var i = validators.length + while (i--) { + if (validators[i].name === validator) { + found = validators[i] + break + } + } + return found + }, - ComponentElement.prototype.attachValidity = function attachValidity () { - this._vm.$el.$validity = this._vm; - }; + _watchModel: function (keypath, fn) { + this._validatorWatchers[keypath] = + this.$watch(keypath, fn, { deep: false, immediate: true }) + }, - ComponentElement.prototype.getValidatorProps = function getValidatorProps$1 () { - var vm = this._vm; - return this._validatorProps(vm._uid.toString(), vm.validators) - }; + _unwatchModel: function (keypath) { + var unwatch = this._validatorWatchers[keypath] + if (unwatch) { + unwatch() + delete this._validatorWatchers[keypath] + } + }, - ComponentElement.prototype.getValue = function getValue () { - var this$1 = this; + _addReadyEvents: function (id, event) { + this._readyEvents[id] = event + }, - var value = {}; - this.getValidatorProps().forEach(function (prop) { - value[prop] = this$1._vnode.child[prop]; - }); - return value - }; + _getReadyEvents: function (id) { + return this._readyEvents[id] + }, - ComponentElement.prototype.checkModified = function checkModified () { - return !looseEqual(this.initValue, this.getValue()) - }; + _isRegistedReadyEvent: function (id) { + return id in this._readyEvents + }, - ComponentElement.prototype.listenToucheableEvent = function listenToucheableEvent () { - this._vm.$el.addEventListener('focusout', this._vm.willUpdateTouched); - }; + _updateDirtyProperty: function (keypath, val) { + var validationName = this._getValidationNamespace('validation') + var dirtyName = this._getValidationNamespace('dirty') - ComponentElement.prototype.unlistenToucheableEvent = function unlistenToucheableEvent () { - this._vm.$el.removeEventListener('focusout', this._vm.willUpdateTouched); - }; + var target = _.getTarget(this[validationName], keypath) + if (target) { + target.$set(dirtyName, this._getInitialValue(keypath) !== val) + } + }, - ComponentElement.prototype.listenInputableEvent = function listenInputableEvent () { - var this$1 = this; + _doValidate: function (keypath, validateName, val) { + var validationName = this._getValidationNamespace('validation') - this.getValidatorProps().forEach(function (prop) { - this$1._watchers.push(this$1._vnode.child.$watch(prop, this$1._vm.watchInputable)); - }); - }; + var target = _.getTarget(this[validationName], keypath) + var validator = this._findValidator(keypath, validateName) + if (target && validator) { + this._invokeValidator( + this._validates[validateName], + val, validator.arg, + function (result) { + target.$set(validateName, !result) + }) + } + }, - ComponentElement.prototype.unlistenInputableEvent = function unlistenInputableEvent () { - this._watchers.forEach(function (watcher) { watcher(); }); - this._watchers = []; - }; + _invokeValidator: function (validator, val, arg, fn) { + var future = validator.call(this, val, arg) + if (typeof future === 'function') { // async + if (future.resolved) { + // cached + fn(future.resolved) + } else if (future.requested) { + // pool callbacks + future.pendingCallbacks.push(fn) + } else { + future.requested = true + var fns = future.pendingCallbacks = [fn] + future(function resolve () { + future.resolved = true + for (var i = 0, l = fns.length; i < l; i++) { + fns[i](true) + } + }, function reject () { + fn(false) + }) + } + } else { // sync + fn(future) + } + } + } + } - return ComponentElement -}; + /** + * Remove properties from target validation + * + * @param {Object} validation + * @param {String} keypath + */ -/* */ -var Elements = function (Vue) { - var SingleElement = SingleElementClass(Vue); - var MultiElement = MultiElementClass(Vue); - var ComponentElement = ComponentElementClass(Vue); + function removeValidationProperties (validation, keypath) { + var keys = keypath.split('.') + var key, obj + while (keys.length) { + key = keys.pop() + if (keys.length !== 0) { + obj = _.getTarget(validation, keys.join('.')) + obj.$delete(key) + } else { + validation.$delete(key) + } + } + } - return { - SingleElement: SingleElement, - MultiElement: MultiElement, - ComponentElement: ComponentElement - } -}; + /** + * Get custom namespace + * + * @param {Object} options + * @return {Object} + */ -/* */ -var Lifecycles = function (Vue) { - var ref = Elements(Vue); - var SingleElement = ref.SingleElement; - var MultiElement = ref.MultiElement; - var ComponentElement = ref.ComponentElement; + function getCustomNamespace (options) { + var namespace = {} + var key + var context + do { + if (options['validator'] && options['validator']['namespace']) { + for (key in options['validator']['namespace']) { + if (!namespace.hasOwnProperty(key)) { + namespace[key] = options['validator']['namespace'][key] + } + } + } + context = options._context || options._parent + if (context) { + options = context.$options + } + } while (context || options._parent) + return namespace + } - function createValidityElement (vm, vnode) { - return vm.multiple - ? new MultiElement(vm) - : checkBuiltInElement(vnode) - ? new SingleElement(vm) - : checkComponentElement(vnode) - ? new ComponentElement(vm, vnode) - : null - } - function watchModelable (val) { - this.$emit('input', { - result: this.result, - progress: this.progress, - progresses: this.progresses - }); - } - - function created () { - this._elementable = null; - - this._keysCached = memoize(function (results) { - return Object.keys(results) - }); - - // for event control flags - this._modified = false; - - // watch validation raw results - this._watchValidationRawResults(); - - var validation = this.$options.propsData ? this.$options.propsData.validation : null; - if (validation) { - var instance = validation.instance; - var name = validation.name; - var group = this.group; - instance.register(this.field, this, { named: name, group: group }); - } - } - - function destroyed () { - var validation = this.$options.propsData ? this.$options.propsData.validation : null; - if (validation) { - var instance = validation.instance; - var name = validation.name; - var group = this.group; - instance.unregister(this.field, { named: name, group: group }); - } - - if (this._unwatchResultProp) { - this._unwatchResultProp(); - this._unwatchResultProp = null; - } - - if (this._unwatchProgressProp) { - this._unwatchProgressProp(); - this._unwatchProgressProp = null; - } - - this._unwatchValidationRawResults(); - - this._elementable.unlistenInputableEvent(); - if (this.autotouch === 'on') { - this._elementable.unlistenToucheableEvent(); - } - this._elementable = null; - } - - function mounted () { - this._elementable = createValidityElement(this, this._vnode); - if (this._elementable) { - if (this.autotouch === 'on') { - this._elementable.listenToucheableEvent(); - } - this._elementable.listenInputableEvent(); - } else { - // TODO: should be warn - } - - if (hasModelDirective(this.$vnode)) { - this._unwatchResultProp = this.$watch('result', watchModelable); - this._unwatchProgressProp = this.$watch('progress', watchModelable); - } - - toggleClasses(this.$el, this.classes.untouched, addClass); - toggleClasses(this.$el, this.classes.pristine, addClass); - } - - return { - created: created, - destroyed: destroyed, - mounted: mounted - } -}; - -function checkComponentElement (vnode) { - return vnode.child && - vnode.componentOptions && - vnode.tag && - vnode.tag.match(/vue-component/) -} - -function checkBuiltInElement (vnode) { - return !vnode.child && - !vnode.componentOptions && - vnode.tag -} - -function hasModelDirective (vnode) { - return ((vnode && vnode.data && vnode.data.directives) || []).find(function (dir) { return dir.name === 'model'; }) -} - -/* */ - -var Event = function (Vue) { - function _fireEvent (type) { - var args = [], len = arguments.length - 1; - while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ]; - - (ref = this).$emit.apply(ref, [ type ].concat( args )); - var ref; - } - - return { - _fireEvent: _fireEvent - } -}; - -/* */ -var State = function (Vue) { - var ref = Vue.util; - var isPlainObject = ref.isPlainObject; - - function getValue (options) { - return this._elementable.getValue() - } - - function checkModified () { - return this._elementable.checkModified() - } - - function willUpdateTouched (options) { - if (!this.touched) { - this.touched = true; - toggleClasses(this.$el, this.classes.touched, addClass); - toggleClasses(this.$el, this.classes.untouched, removeClass); - this._fireEvent('touched'); - } - } - - function willUpdateDirty () { - if (!this.dirty && this.checkModified()) { - this.dirty = true; - toggleClasses(this.$el, this.classes.dirty, addClass); - toggleClasses(this.$el, this.classes.pristine, removeClass); - this._fireEvent('dirty'); - } - } - - function willUpdateModified () { - var modified = this.modified = this.checkModified(); - if (this._modified !== modified) { - this._modified = modified; - toggleClasses(this.$el, this.classes.modified, modified ? addClass : removeClass); - this._fireEvent('modified', modified); - } - } - - function handleInputable (e) { - this.willUpdateDirty(); - this.willUpdateModified(); - } - - function watchInputable (val) { - this.willUpdateDirty(); - this.willUpdateModified(); - } - - function _initStates (keys, target, init) { - if ( init === void 0 ) init = undefined; - - for (var i = 0; i < keys.length; i++) { - var result = target[keys[i]]; - if (isPlainObject(result)) { - var nestedKeys = Object.keys(result); - _initStates(nestedKeys, result, init); - } else { - target[keys[i]] = init; - } - } - } - - function reset () { - this._unwatchValidationRawResults(); - var keys = this._keysCached(this._uid.toString(), this.results); - _initStates(keys, this.results, undefined); - _initStates(keys, this.progresses, ''); - toggleClasses(this.$el, this.classes.valid, removeClass); - toggleClasses(this.$el, this.classes.invalid, removeClass); - toggleClasses(this.$el, this.classes.touched, removeClass); - toggleClasses(this.$el, this.classes.untouched, addClass); - toggleClasses(this.$el, this.classes.dirty, removeClass); - toggleClasses(this.$el, this.classes.pristine, addClass); - toggleClasses(this.$el, this.classes.modified, removeClass); - this.valid = true; - this.dirty = false; - this.touched = false; - this.modified = false; - this._modified = false; - this._watchValidationRawResults(); - } - - function _walkValid (keys, target) { - var valid = true; - for (var i = 0; i < keys.length; i++) { - var result = target[keys[i]]; - if (typeof result === 'boolean' && !result) { - valid = false; - break - } - if (typeof result === 'string' && result) { - valid = false; - break - } - if (isPlainObject(result)) { - var nestedKeys = Object.keys(result); - valid = _walkValid(nestedKeys, result); - if (!valid) { - break - } - } - } - return valid - } - - function _watchValidationRawResults () { - var this$1 = this; - - this._unwatchResults = this.$watch('results', function (val) { - this$1.valid = _walkValid( - this$1._keysCached(this$1._uid.toString(), this$1.results), - this$1.results - ); - if (this$1.valid) { - toggleClasses(this$1.$el, this$1.classes.valid, addClass); - toggleClasses(this$1.$el, this$1.classes.invalid, removeClass); - } else { - toggleClasses(this$1.$el, this$1.classes.valid, removeClass); - toggleClasses(this$1.$el, this$1.classes.invalid, addClass); - } - - this$1._fireEvent(this$1.valid ? 'valid' : 'invalid'); - }, { deep: true }); - } - - function _unwatchValidationRawResults () { - this._unwatchResults(); - this._unwatchResults = undefined; - delete this._unwatchResults; - } - - function touch () { - this.willUpdateTouched(); - } - - return { - getValue: getValue, - checkModified: checkModified, - willUpdateTouched: willUpdateTouched, - willUpdateDirty: willUpdateDirty, - willUpdateModified: willUpdateModified, - handleInputable: handleInputable, - watchInputable: watchInputable, - reset: reset, - _walkValid: _walkValid, - _watchValidationRawResults: _watchValidationRawResults, - _unwatchValidationRawResults: _unwatchValidationRawResults, - touch: touch - } -}; - -/* */ - -/** - * Forgiving check for a promise - */ -function isPromise (p) { - return p && typeof p.then === 'function' -} - -var Validate = function (Vue) { - var ref = Vue.util; - var extend = ref.extend; - var isPlainObject = ref.isPlainObject; - var resolveAsset = ref.resolveAsset; - - function _resolveValidator (name) { - var options = (this.child && this.child.context) - ? this.child.context.$options - : this.$options; - return resolveAsset(options, 'validators', name) - } - - function _getValidateRawDescriptor ( - validator, - field, - value - ) { - var asset = this._resolveValidator(validator); - if (!asset) { - // TODO: should be warned - return null - } - - var fn = null; - var rule = null; - var msg = null; - if (isPlainObject(asset)) { - if (asset.check && typeof asset.check === 'function') { - fn = asset.check; - } - if (asset.message) { - msg = asset.message; - } - } else if (typeof asset === 'function') { - fn = asset; - } else { - // TODO: should be warned - return null - } - - if (!fn) { - // TODO: should be warned - return null - } - - var props = null; - var validators = this.validators; - if (isPlainObject(validators)) { - if (isPlainObject(validators[validator])) { - if (validators[validator].props && isPlainObject(validators[validator].props)) { - props = validators[validator].props; - } else { - if (validators[validator].rule) { - rule = validators[validator].rule; - } - if (validators[validator].message) { - msg = validators[validator].message; - } - } - } else { - rule = validators[validator]; - } - } - - var descriptor = { fn: fn, value: value, field: field }; - if (rule) { - descriptor.rule = rule; - } - if (msg) { - descriptor.msg = msg; - } - if (props) { - descriptor.props = props; - } - - return descriptor - } - - function _resolveMessage ( - field, - msg, - override - ) { - if (override) { return override } - return msg - ? typeof msg === 'function' - ? msg(field) - : msg - : undefined - } - - function _invokeValidator ( - ref, - value, - cb - ) { - var this$1 = this; - var fn = ref.fn; - var field = ref.field; - var rule = ref.rule; - var msg = ref.msg; - - var future = fn.call(this.child.context, value, rule); - if (typeof future === 'function') { // function - future(function () { // resolve - cb(true); - }, function (err) { // reject - cb(false, this$1._resolveMessage(field, msg, err)); - }); - } else if (isPromise(future)) { // promise - future.then(function () { // resolve - cb(true); - }, function (err) { // reject - cb(false, this$1._resolveMessage(field, msg, err)); - }).catch(function (err) { - cb(false, this$1._resolveMessage(field, msg, err.message)); - }); - } else { // sync - cb(future, future === false ? this._resolveMessage(field, msg) : undefined); - } - } - - function _getValidateDescriptors ( - validator, - field, - value - ) { - var descriptors = []; - - var rawDescriptor = this._getValidateRawDescriptor(validator, this.field, value); - if (!rawDescriptor) { return descriptors } - - if (!rawDescriptor.props) { - var descriptor = { name: validator }; - extend(descriptor, rawDescriptor); - descriptors.push(descriptor); - } else { - var propsKeys = Object.keys(!rawDescriptor.props); - propsKeys.forEach(function (prop) { - var descriptor = { - fn: rawDescriptor.fn, - name: validator, - value: rawDescriptor.value[prop], - field: rawDescriptor.field, - prop: prop - }; - if (rawDescriptor.props[prop].rule) { - descriptor.rule = rawDescriptor.props[prop].rule; - } - if (rawDescriptor.props[prop].message) { - descriptor.msg = rawDescriptor.props[prop].message; - } - descriptors.push(descriptor); - }); - } - - return descriptors - } - - function _syncValidates (field, cb) { - var this$1 = this; - - var validators = this._keysCached(this._uid.toString(), this.results); - var value = this.getValue(); - var descriptors = []; - validators.forEach(function (validator) { - this$1._getValidateDescriptors(validator, field, value).forEach(function (desc) { - descriptors.push(desc); - }); - }); - - var count = 0; - var len = descriptors.length; - descriptors.forEach(function (desc) { - var validator = desc.name; - var prop = desc.prop; - if ((!prop && this$1.progresses[validator]) || (prop && this$1.progresses[validator][prop])) { - count++; - if (count === len) { - cb(this$1._walkValid(this$1._keysCached(this$1._uid.toString(), this$1.results), this$1.results)); - } - return - } - - if (!prop) { - this$1.progresses[validator] = 'running'; - } else { - this$1.progresses[validator][prop] = 'running'; - } - - this$1.$nextTick(function () { - this$1._invokeValidator(desc, desc.value, function (ret, msg) { - if (!prop) { - this$1.progresses[validator] = ''; - this$1.results[validator] = msg || ret; - } else { - this$1.progresses[validator][prop] = ''; - this$1.results[validator][prop] = msg || ret; - } - - count++; - if (count === len) { - cb(this$1._walkValid(this$1._keysCached(this$1._uid.toString(), this$1.results), this$1.results)); - } - }); - }); - }); - } - - // TODO:should be refactor!! - function _validate (validator, value, cb) { - var this$1 = this; - - var descriptor = this._getValidateRawDescriptor(validator, this.field, value); - if (descriptor && !descriptor.props) { - if (this.progresses[validator]) { return false } - this.progresses[validator] = 'running'; - this.$nextTick(function () { - this$1._invokeValidator(descriptor, descriptor.value, function (ret, msg) { - this$1.progresses[validator] = ''; - this$1.results[validator] = msg || ret; - if (cb) { - this$1.$nextTick(function () { - cb.call(this$1, null, ret, msg); - }); - } else { - var e = { result: ret }; - if (msg) { - e['msg'] = msg; - } - this$1._fireEvent('validate', validator, e); - } - }); - }); - } else if (descriptor && descriptor.props) { - var propsKeys = Object.keys(descriptor.props); - propsKeys.forEach(function (prop) { - if (this$1.progresses[validator][prop]) { return } - this$1.progresses[validator][prop] = 'running'; - var values = descriptor.value; - var propDescriptor = { - fn: descriptor.fn, - value: values[prop], - field: descriptor.field - }; - if (descriptor.props[prop].rule) { - propDescriptor.rule = descriptor.props[prop].rule; - } - if (descriptor.props[prop].message) { - propDescriptor.msg = descriptor.props[prop].message; - } - this$1.$nextTick(function () { - this$1._invokeValidator(propDescriptor, propDescriptor.value, function (result, msg) { - this$1.progresses[validator][prop] = ''; - this$1.results[validator][prop] = msg || result; - var e = { prop: prop, result: result }; - if (msg) { - e['msg'] = msg; - } - this$1._fireEvent('validate', validator, e); - }); - }); - }); - } else { - // TODO: - var err = new Error(); - cb ? cb.call(this, err) : this._fireEvent('validate', validator, err); - } - return true - } - - // TODO: should be re-design of API - function validate () { - var this$1 = this; - var args = [], len = arguments.length; - while ( len-- ) args[ len ] = arguments[ len ]; - - var validators; - var value; - var cb; - var ret = true; - - if (args.length === 3) { - validators = [args[0]]; - value = args[1]; - cb = args[2]; - } else if (args.length === 2) { - if (isPlainObject(args[0])) { - validators = [args[0].validator]; - value = args[0].value || this.getValue(); - cb = args[1]; - } else { - validators = this._keysCached(this._uid.toString(), this.results); - value = args[0]; - cb = args[1]; - } - } else if (args.length === 1) { - validators = this._keysCached(this._uid.toString(), this.results); - value = this.getValue(); - cb = args[0]; - } else { - validators = this._keysCached(this._uid.toString(), this.results); - value = this.getValue(); - cb = null; - } - - if (args.length === 3 || (args.length === 2 && isPlainObject(args[0]))) { - ret = this._validate(validators[0], value, cb); - } else { - validators.forEach(function (validator) { - ret = this$1._validate(validator, value, cb); - }); - } - - return ret - } - - return { - _resolveValidator: _resolveValidator, - _getValidateRawDescriptor: _getValidateRawDescriptor, - _getValidateDescriptors: _getValidateDescriptors, - _resolveMessage: _resolveMessage, - _invokeValidator: _invokeValidator, - _validate: _validate, - _syncValidates: _syncValidates, - validate: validate - } -}; - -/* */ - -var Methods = function (Vue) { - var ref = Vue.util; - var extend = ref.extend; - - var methods = {}; - extend(methods, Event(Vue)); - extend(methods, State(Vue)); - extend(methods, Validate(Vue)); - - return methods -}; - -/* */ - -var ValidityControl = function (Vue) { - var ref = Vue.util; - var extend = ref.extend; - - var ref$1 = States(Vue); - var props = ref$1.props; - var data = ref$1.data; - var computed = Computed(Vue); - var lifecycles = Lifecycles(Vue); - var ref$2 = Render(Vue); - var render = ref$2.render; - var methods = Methods(Vue); - - var validity = { - props: props, - data: data, - render: render, - computed: computed, - methods: methods - }; - extend(validity, lifecycles); - - return validity -}; - -/* */ -var Validity = function (Vue) { - var ref = Vue.util; - var extend = ref.extend; - - return { - functional: true, - props: baseProps, - render: function render ( - h, - ref - ) { - var props = ref.props; - var data = ref.data; - var children = ref.children; - - return children.map(function (child) { - if (!child.tag) { return child } - var newData = extend({}, data); - newData.props = extend({}, props); - // TODO: should be refactored - newData.props.classes = extend(extend(extend({}, DEFAULT_CLASSES), Vue.config.validator.classes), newData.props.classes); - newData.props.child = child; - return h('validity-control', newData) - }) - } - } -}; - -/* */ -var ValidityGroup = function (Vue) { - var ref = Vue.util; - var extend = ref.extend; - - var props = extend({ - tag: { - type: String, - default: 'fieldset' - } - }, baseProps); - - return { - functional: true, - props: props, - render: function render ( - h, - ref - ) { - var props = ref.props; - var data = ref.data; - var children = ref.children; - - var child = h(props.tag, children); - var newData = extend({}, data); - newData.props = extend({}, props); - // TODO: should be refactored - newData.props.classes = extend(extend(extend({}, DEFAULT_CLASSES), Vue.config.validator.classes), newData.props.classes); - newData.props.child = child; - newData.props.multiple = true; - return h('validity-control', newData) - } - } -}; - -/* */ - -var Validation = function (Vue) { - var ref = Vue.util; - var extend = ref.extend; - - return { - functional: true, - props: { - name: { - type: String - }, - tag: { - type: String, - default: 'form' - } - }, - render: function render ( - h, - ref - ) { - var props = ref.props; - var data = ref.data; - var parent = ref.parent; - var children = ref.children; - var slots = ref.slots; - - if (!parent._validation) { - // TODO: should be warned - return children - } - var tag = props.tag || 'form'; - walkChildren(parent._validation, props.name, children); - var newData = extend({ attrs: {}}, data); - if (tag === 'form') { - newData.attrs.novalidate = true; - } - return h(tag, newData, children) - } - } -}; - -function walkChildren (validation, name, children) { - children.forEach(function (child) { - if (child && - child.componentOptions && - child.componentOptions.propsData && child.componentOptions.tag === 'validity-control') { - child.componentOptions.propsData.validation = { - instance: validation, - name: name - }; - } - child.children && walkChildren(validation, name, child.children); - }); -} - -/* */ -var Component = function (Vue) { - return { - 'validity-control': ValidityControl(Vue), - 'validity': Validity(Vue), - 'validity-group': ValidityGroup(Vue), - 'validation': Validation(Vue) - } -}; - -/* */ -// TODO: should be defined strict type -function mapValidation (results) { - var res = {}; - - normalizeMap(results).forEach(function (ref) { - var key = ref.key; - var val = ref.val; - - res[key] = function mappedValidation () { - var validation = this.$validation; - if (!this._isMounted) { - return null - } - var paths = val.split('.'); - var first = paths.shift(); - if (first !== '$validation') { - warn(("unknown validation result path: " + val)); - return null - } - var path; - var value = validation; - do { - path = paths.shift(); - value = value[path]; - } while (paths.length > 0 && value !== undefined) - return value - }; - }); - - return res -} - -// TODO: should be defined strict type -function normalizeMap (map) { - return Array.isArray(map) - ? map.map(function (key) { return ({ key: key, val: key }); }) - : Object.keys(map).map(function (key) { return ({ key: key, val: map[key] }); }) -} - -/* */ -var installed = false; - -function plugin (Vue, options) { - if ( options === void 0 ) options = {}; - - if (installed) { - warn('already installed.'); - return - } - - Config(Vue); - Asset(Vue); - installMixin(Vue); - installComponent(Vue); - installed = true; -} - -function installMixin (Vue) { - Vue.mixin(Mixin(Vue)); -} - -function installComponent (Vue) { - var components = Component(Vue); - Object.keys(components).forEach(function (id) { - Vue.component(id, components[id]); - }); -} - -plugin.mapValidation = mapValidation; // for standalone -plugin.version = '3.0.0-alpha.2'; - -if (typeof window !== 'undefined' && window.Vue) { - window.Vue.use(plugin); -} - -var index = { - install: plugin, - mapValidation: mapValidation -}; - -return index; - -}))); +/***/ } +/******/ ]) +}); +;