//= require pikaday //= require autonumeric /* DOCUMENTATION ============== Examples ------------- Plain Text Inputs Email Inputs Date Inputs Number Inputs Required positive number with upper unrestricted bounds Options ------------- type -> alias (plain text - no type) calendar -> calendar, date percent -> percent number -> number, numeric money -> money, currency email -> email precision (null) Used on any number type (percent, number, money) to set the amount of decimals used. The defaults are 2 for numbers, 0 for percent, and 3 for money min (null) Sets the minimum value on number types (percent, number, money). restrictMin (true) Used to show a message rather than restrict actual input max (null) Sets the maximum value on number types (percent, number, money). restrictMax (true) Used to show a message rather than restrict actual input placeholder (null) Used to set the placeholder required (false) Used to show a message if the field is empty validate (true) Validates the format of the input if available. Currently this only supports the following types (email, date, unrestricted min and max) toString (false) Return the string version of the input rather than either a number or a date noIcon (false) Used to remove the icon if the field has one. Only effects Date types right now. */ (function() { "use strict"; App.register('component').enter(function() { var template = '
\ \ \ \ \ \ \ \ \ \ \ \
\
{{ message }}

Format: {{ inputFormat }}

\
\
' var inputTypeMap = { 'money':'money', 'currency':'money', 'number':'number', 'numeric':'number', 'date':'date', 'calendar':'date', 'percent':'percent', 'bool':'bool', 'check':'bool', 'boolean':'bool', 'toggle': 'toggle', 'text':'text', 'email':'text', 'phone':'text', 'option': 'radio', 'radio': 'radio', 'select':'select', 'list':'select' } var dataTypeMap = { 'money':'number', 'currency':'number', 'number':'number', 'integer':'number', 'float':'number', 'numeric':'number', 'date':'date', 'calendar':'date', 'percent':'number', 'bool':'bool', 'check':'bool', 'boolean':'bool', 'toggle':'toggle', 'text':'string', 'radio':'radio', 'select':'select' } var numericDefaults = { 'money': {aSign: '$', mDec: '2', wEmpty: 'empty'}, 'percent': {aSign: '%', pSign: 's', mDec: '0', wEmpty: 'empty'}, 'number': {wEmpty: 'empty'}, 'integer': {mDec: '0', wEmpty: 'empty'} } Vue.component('vue-input', { mixins: [App.vue.interfaces.formValidation, App.vue.interfaces.contentValidators, App.vue.interfaces.helpers], template: template, props: { 'type': { default: 'plain' }, 'precision': { default: null }, 'min': { default: null }, 'max': { default: null }, 'numberLabel': { default: null }, 'numberPostLabel': { default: null }, 'numberPreLabel': { default: null }, 'restrictMax': { default: true }, 'restrictMin': { default: true }, 'placeholder': { default: null }, 'required': { default: false }, 'validate': { default: true }, 'toString': { default: false }, 'noIcon': { default: false }, 'value': { twoWay: true }, 'keyCodes': { default: true }, 'id': { default: null }, 'name': { default: null }, 'optionsForSelect': { default: function() {return [];} }, 'disabled': { default: false } }, data: function() { return { inputValue: null, message: null, inputFormat: null, validating: false, formatting: true, renderHTML: false, obj: null, showInput: false, initialValue: this.value, } }, ready: function() { if (this._valueIsEmpty(this.id)) { this.id = this._randomId(); } // set the initial value if (this.isDate) { if (this._valueIsEmpty(this.value)) { this.inputValue = this.value; }else{ this.inputValue = moment(this.value).format(this._formatForDate()); } }else{ this.inputValue = this.value; } this.renderHTML = true; var self = this; this.$nextTick(function(){ self.setupNumber(); self.setupDate(); self.validating = true; $(self.$els.input).on('focus', self.validateContent); }); }, beforeDestroy: function() { try { $(self.$els.input).off('focus'); $(this.$els.input).autoNumeric('destroy'); this.obj.destroy(); }catch(err){} }, watch: { disabled: function(newValue) { if (newValue) { this.validateContent(); } }, inputValue: function(newValue) { if (this.toString) { this.value = String(newValue); }else if (this.isDate) { if (this._valueIsEmpty(newValue)) { this.value = null; }else{ this.value = new Date(newValue); } }else if (this.isNumber){ try{ this.value = $(this.$els.input).autoNumeric('get'); }catch(e){ this.value = newValue; } }else{ this.value = newValue; } this.formatContent(); this.validateContent(); } }, methods: { setupDate: function() { if (this.isDate) { var options = { field: this.$els.input, format: this._formatForDate() }; if (this.hasRestrictedMax) { options['maxDate'] = new Date(this.max); } if (this.hasRestrictedMin) { options['minDate'] = new Date(this.min); } this.obj = new Pikaday(options); } }, setupNumber: function() { if (this.isNumber) { var baseOptions = numericDefaults[this.type] || numericDefaults[this.dataType] || {}; if (this.precision) { baseOptions['mDec'] = this.precision; } if (this.hasRestrictedMax) { baseOptions['vMax'] = this.max; } if (this.hasRestrictedMin) { baseOptions['vMin'] = this.min; } if (this.numberPostLabel || this.numberLabel) { baseOptions['aSign'] = this.numberPostLabel || this.numberLabel; baseOptions['pSign'] = 's'; }else if (this.numberPreLabel) { baseOptions['aSign'] = this.numberPreLabel; baseOptions['pSign'] = 'p'; } var self = this; $(this.$els.input).autoNumeric('init', baseOptions).on('keyup', function() { self.value = $(self.$els.input).autoNumeric('get'); }); $(this.$els.input).autoNumeric('set', this.inputValue); } }, showInputFor: function(type) { if (!this.renderHTML) { return false; } return this.dataType === type; }, incrementValue: function() { if (this.keyCodes) { if (this.isDate) { this.obj.nextMonth(); } if (this.isNumber) { if (this.inputValue < this.max) { this.inputValue++; } } } }, decrementValue: function() { if (this.keyCodes) { if (this.isDate) { this.obj.prevMonth(); } if (this.isNumber) { if (this.inputValue > this.min) { this.inputValue--; } } } }, activeObject: function() { if (this.isDate) { this.obj.show(); } }, formatContent: function() { if (this.formatting) { if (this.type === 'phone' && this._valueIsPhone(this.inputValue)) { this.inputValue = App.vue.interfaces.formatters.methods._formatToPhoneNumber(this.inputValue); } } }, validateContent: function() { this.message = null; this.inputFormat = null; if (this.validating && !this.disabled) { if (this._valueIsEmpty(this.inputValue)) { if (this.required) { this.message = "This can't be empty"; this.inputFormat = this._formatForEmpty(); return false; }else{ // Empty but not required return true; } } if (this.validate) { if (this.type === 'email') { var res = this._valueIsEmail(this.inputValue); if (!res) { this.message = "Not a valid email address."; this.inputFormat = this._formatForEmail(); } return res; }else if (this.type === 'phone') { var res = this._valueIsPhone(this.inputValue); if (!res) { this.message = "Not a valid phone number."; this.inputFormat = this._formatForPhone(); } return res; }else if (this.isDate) { var res = this._valueIsDate(this.inputValue); if (!res) { this.message = "Not a valid date."; this.inputFormat = this._formatForDate(); } return res; }else if (this.isNumber) { if (this.hasUnrestrictedMax && numeral(this.inputValue).value() > this.max) { this.message = "Number out of range."; this.inputFormat = "less than or equal to " + this.max; }else if (this.hasUnrestrictedMin && numeral(this.inputValue).value() < this.min) { this.message = "Number out of range."; this.inputFormat = "greater than or equal to " + this.min; } }else{ return true; } } } return true; }, optionValue: function(option) { return option.value || option; }, optionLabel: function(option) { return option.label || option; } }, computed: { inputType: function() { return inputTypeMap[this.type] || 'text'; }, dataType: function() { return dataTypeMap[this.inputType] || 'string'; }, isNumber: function() { if (this.dataType === 'number') { return true; }else{ return false; } }, isDate: function() { if (this.dataType === 'date') { return true; }else{ return false; } }, isBool: function() { if (this.dataType === 'bool') { return true; }else{ return false; } }, isString: function() { if (this.dataType === 'string') { return true; }else{ return false; } }, hasRestrictedMax: function() { if (this.max !== null && this.restrictMax) { return true; }else{ return false; } }, hasRestrictedMin: function() { if (this.min !== null && this.restrictMin) { return true; }else{ return false; } }, hasUnrestrictedMax: function() { if (this.max !== null && !this.restrictMax) { return true; }else{ return false; } }, hasUnrestrictedMin: function() { if (this.min !== null && !this.restrictMin) { return true; }else{ return false; } }, inputIcon: function() { if (this.isDate && !this.init) { return 'fa-calendar'; } } } }); }); })();